【问题标题】:How to use JsonTextReader twice如何使用 JsonTextReader 两次
【发布时间】:2012-03-05 22:23:20
【问题描述】:

我得到一个 json 数据流,其中包含一个名为“type”的字段。该类型字段描述了需要在运行时创建的对象的类型。看起来我无法使用 JsonTextReader 两次,并且无法将文本阅读器重置为开头。

using (var streamReader = new StreamReader(stream, Encoding))
using (var jsonTextReader = new JsonTextReader(streamReader))
{
    JToken token = JObject.Load(jsonTextReader);
    var type = (string) token.SelectToken("type");
    var modelType = Type.GetType("Project." + type + ", Project");

    // Fails here
    var obj = serializer.Deserialize(jsonTextReader, modelType);
}

我收到此错误消息。 反序列化对象时出现意外令牌:EndObject。

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    您可以从 JToken 创建一个 JsonReader。

    JsonReader reader = token.CreateReader();
    

    【讨论】:

    • 当您要查找的类型在泛型数组中时不起作用,例如 >
    【解决方案2】:

    要将您的阅读器重置为开始,请将基础流的 Position 属性设置为 0。

    streamReader.BaseStream.Position = 0;
    

    编辑: 虽然这将重置您的基础流,但 jsonTextReader 根据定义是forward-only,这意味着它的行号和位置是只读的。为此,您必须重置 streamReader 位置,然后将其输入 new JsonTextReader 对象。

    不幸的是,Phil,没有办法读取 JsonTextReader 两次,因为它是只进的。

    参考: http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm "表示提供对序列化 Json 数据的快速、非缓存、只进访问的读取器。"

    【讨论】:

    • 你确定这会正常工作吗? StreamReaderJsonTextReader 都可能保持内部状态,这样做不会被重置。
    【解决方案3】:

    根据 James Newton King 的建议,我将介绍以高效内存格式使用 JsonTextReader,避免使用大对象堆等 in my blog。您可以利用此代码和提供的代码多次读取 JSON,而无需担心 JsonTextReader 的底层实现。

    随时欢迎评论和反馈。

    【讨论】:

      【解决方案4】:

      我做了一些更多的测试,发现以下工作。

      1. 设置JsonTextReader.CloseInput = false
      2. 销毁JsonTextReader(通过关闭using 语句)
      3. 设置StreamReader.BaseStream.Position = 0
      4. 创建一个新的JsonTextReader

      看起来像这样:

      using (var streamReader = new StreamReader(stream, encoding))
      {
          Type modelType = null;
      
          using (var jsonTextReader = new JsonTextReader(streamReader))
          {
              jsonTextReader.CloseInput = false;
      
              JToken token = JObject.Load(jsonTextReader);
              string type = (string)token.SelectToken("type");
              modelType = Type.GetType("Project." + type + ", Project");
          }
      
          streamReader.BaseStream.Position = 0;
      
          using (var jsonTextReader = new JsonTextReader(streamReader))
          {
              var obj = serializer.Deserialize(jsonTextReader, modelType);
          }
      
      }
      

      【讨论】:

      • 这行不通。除非您在StreamReader 的构造函数中指定leaveOpen 参数,否则它将关闭底层流。如果你解决了这个问题,如果问题中的代码有效,这可能有效,但它没有。
      • 我的原帖已经过测试,但不正确。我已经更新了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      相关资源
      最近更新 更多