在.NET中解析大型json文件

时间:2015-08-26 13:03:42

标签: c# json.net deserialization json-deserialization

我用过" JsonConvert.Deserialize(json)"到目前为止,Json.Net的方法运作良好,说实话,我不需要更多的东西。

我正在开发一个后台(控制台)应用程序,该应用程序不断从不同的URL下载json内容,然后将结果反序列化为.Net对象列表。

 using (WebClient client = new WebClient())
 {
      string json = client.DownloadString(stringUrl);

      var result = JsonConvert.DeserializeObject<List<Contact>>(json);

 }

上面的简单代码片段似乎并不完美,但它可以完成这项工作。当文件很大(15000个联系人 - 48 MB文件)时,JsonConvert.DeserializeObject不是解决方案,并且该行抛出异常类型的JsonReaderException。

下载的json是一个数组,这就是样本的样子。 Contact是反序列化的json对象的容器类。

[
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  }
]

我最初的猜测是内存不足。出于好奇,我试图将其解析为JArray,这也导致了同样的异常。

我已经开始深入研究Json.Net文档并阅读类似的主题。由于我还没有设法制作出有效的解决方案,我决定在这里发一个问题。

我很感激任何建议/代码段,它可以帮助我研究问题,了解更多信息并最终找到解决方案。

谢谢:)

更新:逐行反序列化时,我得到了同样的错误:&#34; [路径&#39;,第600003行,第1位。&#34;所以我做的是下载其中两个并在Notepad ++中检查它们。我注意到的是,如果数组长度超过12000,则在第12000个元素之后&#34; [&#34;关闭,另一个数组启动。换句话说,json看起来完全像这样:

[
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  }
]
[
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  },
  {
    "firstname": "sometext",
    "lastname": "sometext"
  }
]

1 个答案:

答案 0 :(得分:16)

Json.NET支持直接从流中反序列化。下面是一种使用StreamReader反序列化JSON的方法,一次只读取一个JSON字符串,而不是将整个JSON字符串加载到内存中。

using (WebClient client = new WebClient())
{
    using (StreamReader sr = new StreamReader(client.OpenRead(stringUrl)))
    {
        using (JsonReader reader = new JsonTextReader(sr))
        {
            JsonSerializer serializer = new JsonSerializer();

            // read the json from a stream
            // json size doesn't matter because only a small piece is read at a time from the HTTP request
            IList<Contact> result = serializer.Deserialize<List<Contact>>(reader);
        }
    }
}

参考:JSON.NET Performance Tips