Comment sérialiser byte [] comme un simple tableau JSON et non comme base64 dans JSON.net?
J'utilise JSON.net pour sérialiser Certains objets entre C# et JavaScript. Les données JSON sont transférées via WebSocket entre l'application. net et le navigateur.
Dans la structure de données il y a quelques byte[]
champs, je veux ces champs comme un Array
en JavaScript aussi.
Comment puis-je sérialiser un C # byte[]
dans un tableau JSON simple comme [ 0 , 1 , 254, 255 ]
au lieu d'une chaîne base64?
3 réponses
La façon la plus simple de penser est de convertir le tableau d'octets en un tableau entier, comme:
var intArray = byteArray.Select(b => (int)b).ToArray();
Cela ne nécessiterait aucune gestion spéciale de la bibliothèque JSON, ni aucune sérialisation personnalisée ou quelque chose comme ça.
EDIT : cela signifierait avoir à personnaliser votre objet de données pour gérer le type différent. Peut-être:
public class CustomFoo : Foo
{
// SomeBytesHere is a byte[] in the base class
public new int[] SomeBytesHere { get;set; }
}
Alors peut-être que ce n'est pas le plus simple-en fonction de la quantité de choses que vous devez sérialiser
JSON.NET sélectionne le BinaryConverter
pour lire et écrire un tableau d'octets. Vous pouvez voir dans la source {[8] } qu'elle utilise l'opération WriteValue
sur la classe JsonWriter
avec le tableau d'octets qui les amène à être écrits en Base-64.
Pour modifier cela, vous pouvez écrire votre propre convertisseur qui lit et écrit un tableau dans le format que vous attendez:
public class ByteArrayConverter : JsonConverter
{
public override void WriteJson(
JsonWriter writer,
object value,
JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
return;
}
byte[] data = (byte[])value;
// Compose an array.
writer.WriteStartArray();
for (var i = 0; i < data.Length; i++)
{
writer.WriteValue(data[i]);
}
writer.WriteEndArray();
}
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
var byteList = new List<byte>();
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Integer:
byteList.Add(Convert.ToByte(reader.Value));
break;
case JsonToken.EndArray:
return byteList.ToArray();
case JsonToken.Comment:
// skip
break;
default:
throw new Exception(
string.Format(
"Unexpected token when reading bytes: {0}",
reader.TokenType));
}
}
throw new Exception("Unexpected end when reading bytes.");
}
else
{
throw new Exception(
string.Format(
"Unexpected token parsing binary. "
+ "Expected StartArray, got {0}.",
reader.TokenType));
}
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(byte[]);
}
}
Vous utiliseriez ceci en appliquant le JsonConverterAttribute
au membre:
[JsonConverter(typeof(ByteArrayConverter))]
public byte[] Data { get; set; }
Ref ma réponse , JSON.net peut personnaliser la sérialisation dans le paramètre pour tous au lieu de l'attribut dans la propriété.
Vous pouvez facilement le changer de base64 en tableau de nombres, il suffit d'écrire une valeur brute CSV entre crochets.