【问题标题】:Load multiple concatenated JSON objects from stream从流中加载多个连接的 JSON 对象
【发布时间】:2015-04-06 18:36:19
【问题描述】:

我阅读了几个类似的问题,但没有找到任何与 JObject 相关的问题。这是问题所在:我有一个带有连接 JSON 对象的流,即:

{"key1":"value1"}{"key2":"value2"}{"key3":"value3"}

现在,我想将这些对象一一读入JObject。以下是我尝试的方法:

public class JsonStreamReader : JsonTextReader
{
    public JsonStreamReader(Stream s) : base(new StreamReader(s)) {}
}

private void LoadJson(Stream s)
{
    var r = new JsonStreamReader(s) { SupportMultipleContent = true };
    var obj = JObject.Load(r);
    // ... get data from JObject ...
}

这里的问题是 JObject.Load() 从流中读取所有可用数据,但只解析第一个对象并丢弃所有其余对象。 我该如何处理?

如果出现 XY 问题(我为什么需要它): 我想通过 TCP 流传输 JSON 消息。因为我使用原始 TCP 流,所以我需要知道消息的大小才能读取它。我决定在每条消息之前用sizemessage type 写小标题,这样我就可以将标题读入一个小缓冲区,获取以下消息的大小,然后将其完整读取。

【问题讨论】:

  • 有什么方法可以将 JSON 对象包装到一个数组中并用逗号分隔它们?
  • @krillgar 所以这将是一个单一的对象?
  • 是上面的文字 json 吗?大多数具有这种数据格式的 API 都会传递 json 对象以新行分隔,因此处理它的正确方法是逐行读取,将每个对象传递给 JObject.Load(可能需要不同的方法),而不是尝试全部完成一次。
  • 嗯,一个数组,这样你就可以将它反序列化为你的对象的 IEnumerable。否则,您将不得不想出一种方法将字符串解析为单独的对象并将每个对象转换为列表。我刚刚尝试使用dynamic,但遇到了解析错误(如预期的那样)。现在,您的 Stream 是无效的 JSON。
  • @krillgar 我强烈建议不要转换 json 预反序列化。对象不是以数组形式传递的,因为它是一个流。 API 被设计为以我上面描述的方式使用,重写响应极易出错且效率低下。

标签: c# json json.net


【解决方案1】:

您可以通过将 JsonReader 上的 SupportMultipleContent 设置为 true 来实现:

Read Multiple Fragments With JsonReader

如果将 JObject.Load 与该设置一起使用时出现问题,请改用 JsonConvert.DeserializeObject。

【讨论】:

  • 完美的解决方案,除了一件事:阅读器从流中读取所有可用数据。我希望它只读取一个对象(因此流位置将是原始位置+读取对象的长度),原因有两个:1]可能有部分对象尚未完全接收; 2] 以下对象旨在被其他层的消息传递协议读取。
猜你喜欢
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多