如何使用JsonTextReader两次

时间:2012-03-05 22:23:21

标签: c# json json.net

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

4 个答案:

答案 0 :(得分:14)

您可以从JToken创建一个JsonReader。

JsonReader reader = token.CreateReader();

答案 1 :(得分:2)

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

streamReader.BaseStream.Position = 0;

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

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

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

答案 2 :(得分:1)

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

欢迎提出意见和反馈。

答案 3 :(得分:0)

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

  1. 设置JsonTextReader.CloseInput = false
  2. 销毁JsonTextReader(通过关闭using声明)
  3. 设置StreamReader.BaseStream.Position = 0
  4. 制作新的JsonTextReader
  5. 它看起来像这样:

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