Как сериализовать byte [] как простой массив JSON, а не как base64 в JSON.net?
Я использую JSON.net для сериализации некоторых объектов между С# и JavaScript. Данные JSON передаются через WebSocket между .NET и браузером.
В структуре данных есть несколько полей byte[]
, я хочу, чтобы эти поля были как Array
в JavaScript.
Как я могу сериализовать С# byte[]
в простой массив JSON как [ 0 , 1 , 254, 255 ]
вместо строки base64?
Ответы
Ответ 1
Самый простой способ, который я могу представить, - преобразовать массив байтов в целочисленный массив, например:
var intArray = byteArray.Select(b => (int)b).ToArray();
Это не потребует специальной обработки библиотеки JSON или какой-либо пользовательской сериализации или чего-либо подобного.
EDIT. Это означало бы необходимость настраивать ваш объект данных для обработки другого типа. Может быть:
public class CustomFoo : Foo
{
// SomeBytesHere is a byte[] in the base class
public new int[] SomeBytesHere { get;set; }
}
Так что, возможно, это не самый простой - в зависимости от того, сколько материала вам нужно сериализовать
Ответ 2
JSON.NET выбирает BinaryConverter
для чтения и записи массива байтов. В источнике вы можете видеть, что он использует операцию WriteValue
в классе JsonWriter
с массивом байтов, который заставляет их записываться как Base-64.
Чтобы изменить это, вы можете написать собственный конвертер, который считывает и записывает массив в ожидаемом формате:
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[]);
}
}
Вы использовали бы это, применив JsonConverterAttribute
к члену:
[JsonConverter(typeof(ByteArrayConverter))]
public byte[] Data { get; set; }