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

31
我使用JSON.net在C#和JavaScript之间序列化一些对象。JSON数据通过WebSocket在.NET和浏览器应用程序之间传输。
在数据结构中,有一些byte[]字段,我也希望在JavaScript中将这些字段作为一个Array
如何将C#的byte[]序列化为一个简单的JSON数组,例如[ 0 , 1 , 254, 255 ],而不是一个base64字符串?
3个回答

69
JSON.NET正在选择BinaryConverter来读写字节数组。您可以在源代码中看到,它使用JsonWriter类上的WriteValue操作将字节数组写入为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; }

2
提供ByteArrayConverter类将获得额外的积分!但是,有一个小错误。因为您已经在使用JsonWriter,所以没有必要手动添加逗号,因此您可以删除此部分: if(i != data.Length) { writer.WriteRaw(","); } 否则,您的数组将如下所示:[12,,54,,32,,8] - Bram Vandenbussche
这个很好用,看起来也是json接口的正确使用方式。 - Xan-Kun Clark-Davis
优秀的答案 - stackmalux

17

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

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

这不需要对JSON库进行特殊处理,也不需要进行任何自定义序列化或类似的操作。 编辑: 这意味着需要定制您的数据对象来处理不同的类型。也许可以这样:
public class CustomFoo : Foo
{
    // SomeBytesHere is a byte[] in the base class
    public new int[] SomeBytesHere { get;set; }
}

也许这不是最简单的 - 取决于您需要序列化多少内容


我喜欢“int Array”解决方案。它非常好用且易于实现。非常感谢您的提示。 - Marcus
太棒了。一个字节可以适应一个int,整个int[]是一个字节数组。在另一端使用JSON绑定的WCF可以接收一个带有byte[]属性的JSON序列化DTO,并且可以安全地反序列化它,而无需任何自定义格式化程序或base64解码/流写入。 序列化后的JSON大小相当惊人,但它确实有效! - Chris Kissinger
1
它将使用字节数组的8倍内存,因此并非始终可行的解决方案。 - FINDarkside

1

参考 我的回答,JSON.net可以在设置中自定义序列化,而不是在属性中使用属性。

您可以轻松地将其从base64更改为数字数组,只需编写方括号csv原始值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接