【问题标题】:Serialize Newtonsoft JSON to byte array将 Newtonsoft JSON 序列化为字节数组
【发布时间】:2019-03-10 01:30:58
【问题描述】:

我的目标是在字节数组的字段中发送包含标头对象和压缩数据的 JSON。

[JsonObject(MemberSerialization.OptOut)]
public class Message
{
    public Message()
    {
        Header = new Header();
    }

    public Header Header { get; set; }


    public byte[] Data { get; set; }
}

字节数组是 gzip 压缩的 JSON 对象,但这无关紧要。我遇到的问题是,如果我序列化 JSON,它会转换为字符串,然后再转换回字节。问题是,消息大小增加了很多,因为序列化字节数组会将其转换为字符串表示形式。

我受到最大消息大小的限制,并且我已经在适当的位置吐出压缩数据,但是当我发送包含字节数组和未压缩标头中的压缩数据的 JSON 时,序列化 JSON 对象使我超出了消息大小限制。

是否有任何可靠的方法可以立即将 JSON 对象转换为字节数组。

           var stringMessage = JsonConvert.SerializeObject(message,Formatting.None);
            var bytes = Encoding.UTF8.GetBytes(stringMessage);

            var stringMessage2 = JsonConvert.SerializeObject(message.TransportHeader, Formatting.None);
            var bytes2 = Encoding.UTF8.GetBytes(stringMessage2);

            Message eventMessage = new Message(bytes);
            var bytes3= Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message.Transportdata));

压缩后的数据大小=243905

序列化后的完整 JSON 字节数 = 325313

仅以字节为单位的标头 =90

只是将压缩数据序列化并转换回字节 = 325210,(当数据被 JsonConvert.SerializeObject 序列化并生成字符串表示时,大小会增加)

明显上升了不少,是字节数组引起的。

【问题讨论】:

  • 如果您使用@ygaradon 的答案,请传入MemoryStream,然后使用ToArray() 获取byte[]
  • 不是重复的。他的问题是他的序列化大小出乎意料地大。
  • 您是否考虑过使用多部分/混合内容类型而不是直接的 JSON 通过网络发送数据?将您的 JSON 放在一部分中,将二进制数据放在另一部分中。
  • 存在 JSON 部分,因此可以识别二进制数据并将其拼凑在一起,如果没有 json 标头,就不可能重新组合拆分和压缩的数据。而且我不能单独发送两个,因为无法知道哪个标头属于哪个包。

标签: c# json.net


【解决方案1】:

我找到了一种方法来做我想做的事,它不完全是 JSON,而是 BSON 或也称为二进制 JSON。好吧,既然找到解决方案纯属运气,我不确定 BSON 有多知名。

无论如何,Newtonsoft 通过 https://www.nuget.org/packages/Newtonsoft.Json.Bson/1.0.1 的 Newtonsoft.Json.Bson nuget 包支持它

一些序列化/反序列化的代码

            foreach (var message in transportMessageList)
        {
            MemoryStream ms = new MemoryStream();
            using (BsonDataWriter writer = new BsonDataWriter(ms))
            {
                JsonSerializer serializer = new JsonSerializer();
                serializer.Serialize(writer, message);
            }

            var bsonByteArray = ms.ToArray();
            Assert.True(bsonByteArray.Length!=0);
            bsonList.Add(bsonByteArray);
        }

        var deserializdTransmortMessageList = new List<TransportMessage>();
        foreach (var byteArray in bsonList)
        {
            TransportMessage message;
            MemoryStream ms = new MemoryStream(byteArray);
            using (BsonDataReader reader = new BsonDataReader(ms))
            {
                JsonSerializer serializer = new JsonSerializer();
                message = serializer.Deserialize<TransportMessage>(reader);
            }
            Assert.True(message.Transportdata.Length!=0);
            deserializdTransmortMessageList.Add(message);
        }

您可以使用与 JSON 相同的类/对象,序列化压缩的字节数组不再导致大小增加。

请注意,Newtonsoft 网站上的 BSON 文档已过时,目前仅列出不推荐使用的 api 调用。我的代码使用适当的非弃用 API 调用。

【讨论】:

    【解决方案2】:

    JSON 是一种基于字符的格式,因此必然涉及字符数据。我怀疑您使用了 UTF16 编码,它将每个字符变成两个字节。如果您使用UTF8,您将不会遇到任何有意义的大小开销。

    【讨论】:

    • 我在序列化后使用UTF8获取字节。
    • 那么请发布您的代码以及您遇到的大小扩展类型。
    • 更新了原始帖子,增加了序列化和大小。
    • @AistisTaraskevicius 谢谢。有多少个字符?目前尚不清楚为什么您认为转换为字节会增加大小。相对于您注意到的增加是什么?
    • 如果你看帖子的底部,我指出压缩数据的大小为 243905 字节,当相同的数据被序列化并转换回字节(所以我可以将它发送到天蓝色)大小上升到 325210,当序列化发生时它会上升,字符串表示很长,将其转换回字节对大小没有帮助。
    猜你喜欢
    • 2018-01-11
    • 2021-10-13
    • 2017-10-16
    • 2018-06-26
    • 2013-02-17
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多