如何将byte []序列化为简单的JSON数组而不是JSON.net中的base64?

时间:2022-10-24 14:25:18

I use JSON.net to serialize some objects between C# and JavaScript. The JSON data is transfered via WebSocket between the .NET and browser application.

我使用JSON.net来序列化C#和JavaScript之间的一些对象。 JSON数据通过WebSocket在.NET和浏览器应用程序之间传输。

In the data structure there are some byte[] fields, I want these fields as an Array in JavaScript also.

在数据结构中有一些byte []字段,我也希望这些字段作为JavaScript中的数组。

How can I serialize a C# byte[] to a simple JSON Array like [ 0 , 1 , 254, 255 ] instead of a base64 string?

如何将C#byte []序列化为简单的JSON数组,如[0,1,254,255]而不是base64字符串?

2 个解决方案

#1


12  

Simplest way I can think of is to convert the byte array into an integer array, like:

我能想到的最简单的方法是将字节数组转换为整数数组,如:

var intArray = byteArray.Select(b => (int)b).ToArray();

This wouldn't require any special handling of the JSON library, or any custom serialization or anything like that.

这不需要对JSON库或任何自定义序列化或类似的任何特殊处理。

EDIT: This would mean having to customize your data object to handle the different type. Maybe:

编辑:这意味着必须自定义您的数据对象来处理不同的类型。也许:

public class CustomFoo : Foo
{
    // SomeBytesHere is a byte[] in the base class
    public new int[] SomeBytesHere { get;set; }
}

So maybe it's not the simplest - depending on how much stuff you have to serialize

所以也许它不是最简单的 - 取决于您需要序列化多少东西

#2


43  

JSON.NET is selecting the BinaryConverter to read and write an array of bytes. You can see in the source that it uses the WriteValue operation on the JsonWriter class with the array of bytes which causes them to be written to as Base-64.

JSON.NET正在选择BinaryConverter来读写字节数组。您可以在源代码中看到它在JsonWriter类上使用WriteValue操作,并使用字节数组将它们写入Base-64。

To modify this, you can write your own converter which reads and writes an array in the format you expect:

要修改它,您可以编写自己的转换器,以您期望的格式读取和写入数组:

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[]);
    }
}

You would use this by applying the JsonConverterAttribute to the member:

您可以通过将JsonConverterAttribute应用于成员来使用它:

[JsonConverter(typeof(ByteArrayConverter))]
public byte[] Data { get; set; }

#1


12  

Simplest way I can think of is to convert the byte array into an integer array, like:

我能想到的最简单的方法是将字节数组转换为整数数组,如:

var intArray = byteArray.Select(b => (int)b).ToArray();

This wouldn't require any special handling of the JSON library, or any custom serialization or anything like that.

这不需要对JSON库或任何自定义序列化或类似的任何特殊处理。

EDIT: This would mean having to customize your data object to handle the different type. Maybe:

编辑:这意味着必须自定义您的数据对象来处理不同的类型。也许:

public class CustomFoo : Foo
{
    // SomeBytesHere is a byte[] in the base class
    public new int[] SomeBytesHere { get;set; }
}

So maybe it's not the simplest - depending on how much stuff you have to serialize

所以也许它不是最简单的 - 取决于您需要序列化多少东西

#2


43  

JSON.NET is selecting the BinaryConverter to read and write an array of bytes. You can see in the source that it uses the WriteValue operation on the JsonWriter class with the array of bytes which causes them to be written to as Base-64.

JSON.NET正在选择BinaryConverter来读写字节数组。您可以在源代码中看到它在JsonWriter类上使用WriteValue操作,并使用字节数组将它们写入Base-64。

To modify this, you can write your own converter which reads and writes an array in the format you expect:

要修改它,您可以编写自己的转换器,以您期望的格式读取和写入数组:

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[]);
    }
}

You would use this by applying the JsonConverterAttribute to the member:

您可以通过将JsonConverterAttribute应用于成员来使用它:

[JsonConverter(typeof(ByteArrayConverter))]
public byte[] Data { get; set; }