问题 如何使用JsonTextReader两次


我获得了一个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。


4436
2018-03-05 22:23


起源



答案:


您可以从JToken创建JsonReader。

JsonReader reader = token.CreateReader();

13
2018-03-06 06:17



这就是诀窍!谢谢。 - Phil


答案:


您可以从JToken创建JsonReader。

JsonReader reader = token.CreateReader();

13
2018-03-06 06:17



这就是诀窍!谢谢。 - Phil


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

streamReader.BaseStream.Position = 0;

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

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

参考: http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonTextReader.htm “代表一个读者,它提供对序列化Json数据的快速,非缓存,仅向前访问。”


1
2018-03-06 01:01



你确定这会正常工作吗?这俩 StreamReader 和 JsonTextReader 可能保持内部状态,这样做不会被重置。 - svick


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

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

}

0
2018-03-06 00:30



这不行。除非你指定 leaveOpen 。的构造函数中的参数 StreamReader,它将关闭底层流。如果你修复了这个问题,如果问题中的代码有效,这可能会有效,但事实并非如此。 - svick
我的原始帖子已经过测试,但不正确。我已经更新了。 - tstuts


我用封面来掩盖 JsonTextReader 以内存有效的格式,避免大对象堆等, 在我的博客中,根据James Newton King的建议。您可以利用此代码和提供的代码多次读取JSON,而无需担心底层实现 JsonTextReader

欢迎提出意见和反馈。


0
2017-09-25 15:03