C#Newtonsoft.JSON库在大多数情况下都能很好地工作,但是没有一种简单的方法来读取concatenated JSON,如下所示:
{"some":"thing"}{"some":"other thing"}{"some":"third thing"}
这段代码非常简单,但是如果我尝试反序列化多个对象,则会引发异常:
using (var reader = new StreamReader(File.Open("data.txt", FileMode.Open)))
{
using (var jr = new JsonTextReader(reader))
{
var data1 = js.Deserialize<Data>(jr));
var data2 = js.Deserialize<Data>(jr)); // <--- Exception is thrown here
}
}
有几种解决方法。第一个是将整个对象列表重新格式化为JSON数组。这种方法适用于少量数据,但是如果文件不能容纳在内存中,情况将变得非常复杂。
另一种解决方法是将整个文本拆分为单独的JSON对象,并一次解析一个对象。该解决方案将处理大量数据,但由于需要某种JSON解析,因此实现起来稍微复杂一些。
在这种串联的JSON文件中,有没有更简单的方法来读取JSON对象?
答案 0 :(得分:2)
此解决方案基于Newtonsoft.JSON版本12.0.1。将来可能会也可能不会。
首先,我们需要一个更好的 JsonTextReader ,它将在反序列化JSON对象后重置为可用状态。
public class MyJsonTextReader : JsonTextReader
{
public MyJsonTextReader(TextReader textReader) : base(textReader)
{
SupportMultipleContent = true;
}
public bool ObjectDone()
{
base.SetStateBasedOnCurrent();
try
{
// This call works fine at the end of the file but may throw JsonReaderException
// if some bad character follows our JSON object
return !base.Read();
}
catch (JsonReaderException)
{
return true;
}
}
}
使用新的JSON阅读器类反序列化代码可以进行如下修改:
var all = new List<Data>();
var js = new JsonSerializer();
using (var reader = new StreamReader(File.Open("data.txt", FileMode.Open)))
using (var jr = new MyJsonTextReader(reader))
do
{
all.Add(js.Deserialize<Data>(jr));
} while (!jr.ObjectDone());
此解决方案可以读取不限数量的对象。 ObjectDone()函数在文件末尾或反序列化对象后的字符无效时返回false。