使用 Newtonsoft.JSON 读取多个 JSON 对象(串联 JSON)



C# Newtonsoft.JSON 库在大多数情况下运行良好,但没有简单的方法来读取串联的 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 对象?

此解决方案基于 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。

相关内容

  • 没有找到相关文章

最新更新