C# 如何从大量JSON对象中流式传输每个对象的原始JSON?
请注意,这不是一个重复的问题,因为这是一个关于逐个对象解析(而不是反序列化)大型数组对象并检索原始JSON的问题 我正在处理非常大的JSON有效负载数组(数十GB) 每个对象的结构可能不同,即异构:C# 如何从大量JSON对象中流式传输每个对象的原始JSON?,c#,.net,json,json.net,C#,.net,Json,Json.net,请注意,这不是一个重复的问题,因为这是一个关于逐个对象解析(而不是反序列化)大型数组对象并检索原始JSON的问题 我正在处理非常大的JSON有效负载数组(数十GB) 每个对象的结构可能不同,即异构: [ {"id": "foo", "value": "bar"}, {"key": "foo", "name": "bar", "age": 10}, ... ] 我如何处理每个对象的流,并检索每个对象的原始JSON字符串 我目前的解决方案是使用StreamReader和Js
[
{"id": "foo", "value": "bar"},
{"key": "foo", "name": "bar", "age": 10},
...
]
我如何处理每个对象的流,并检索每个对象的原始JSON字符串
我目前的解决方案是使用StreamReader
和JsonTextReader
使用JObject
反序列化每个对象,然后使用.ToString()
检索JSON。但我更愿意避免性能成本和GC分配压力,因为必须从JSON反序列化才能再次检索JSON
var file = new FileInfo(@"C:\Very.Large.Array.json");
using (var sr = new StreamReader(file.OpenRead()))
using (var reader = new JsonTextReader(sr))
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
var obj = JObject.Load(reader);
var rawJSON = obj.ToString();
}
}
}
我认为您应该使用
JsonTextWriter
以及JsonTextReader
。下面是演示该思想的简单POC类
我想,要使这段代码达到生产质量,还需要一些改进。与此类似,您可以将StringBuilder sb
从局部变量提升到实例字段,并在每次迭代时清除它,而不是创建新对象
但我的目标只是展示基本理念
public class JsonBigFileReader
{
static string ReadSingleObject(JsonTextReader reader)
{
StringBuilder sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var writer = new JsonTextWriter(sw))
{
writer.WriteToken(reader, true); // writes current token including its children (meaning the whole object)
}
}
return sb.ToString();
}
public IEnumerable<string> ReadArray(string fileName)
{
var file = new FileInfo(fileName);
using (var sr = new StreamReader(file.OpenRead()))
using (var reader = new JsonTextReader(sr))
{
reader.Read();
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
yield return ReadSingleObject(reader);
}
}
}
}
}
公共类JsonBigFileReader
{
静态字符串ReadSingleObject(JsonTextReader阅读器)
{
StringBuilder sb=新的StringBuilder();
使用(var sw=新的StringWriter(sb))
{
使用(var writer=newjsontextwriter(sw))
{
WriteToken(reader,true);//写入当前标记,包括其子标记(表示整个对象)
}
}
使某人返回字符串();
}
公共IEnumerable可读数组(字符串文件名)
{
var file=新文件信息(文件名);
使用(var sr=newstreamreader(file.OpenRead()))
使用(var reader=newjsontextreader(sr))
{
reader.Read();
while(reader.Read())
{
if(reader.TokenType==JsonToken.StartObject)
{
产生返回ReadSingleObject(reader);
}
}
}
}
}
我认为您应该使用JsonTextWriter
以及JsonTextReader
。下面是演示该思想的简单POC类
我想,要使这段代码达到生产质量,还需要一些改进。与此类似,您可以将StringBuilder sb
从局部变量提升到实例字段,并在每次迭代时清除它,而不是创建新对象
但我的目标只是展示基本理念
public class JsonBigFileReader
{
static string ReadSingleObject(JsonTextReader reader)
{
StringBuilder sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var writer = new JsonTextWriter(sw))
{
writer.WriteToken(reader, true); // writes current token including its children (meaning the whole object)
}
}
return sb.ToString();
}
public IEnumerable<string> ReadArray(string fileName)
{
var file = new FileInfo(fileName);
using (var sr = new StreamReader(file.OpenRead()))
using (var reader = new JsonTextReader(sr))
{
reader.Read();
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
yield return ReadSingleObject(reader);
}
}
}
}
}
公共类JsonBigFileReader
{
静态字符串ReadSingleObject(JsonTextReader阅读器)
{
StringBuilder sb=新的StringBuilder();
使用(var sw=新的StringWriter(sb))
{
使用(var writer=newjsontextwriter(sw))
{
WriteToken(reader,true);//写入当前标记,包括其子标记(表示整个对象)
}
}
使某人返回字符串();
}
公共IEnumerable可读数组(字符串文件名)
{
var file=新文件信息(文件名);
使用(var sr=newstreamreader(file.OpenRead()))
使用(var reader=newjsontextreader(sr))
{
reader.Read();
while(reader.Read())
{
if(reader.TokenType==JsonToken.StartObject)
{
产生返回ReadSingleObject(reader);
}
}
}
}
}
将返回类型更改为IEnumerablet这并不能回答我的问题,我正在寻找一种不必将JSON反序列化为对象的方法。我的问题不是收益率回归,这就是为什么它是一个评论。答案是更改您的文件。假设文件以任何方式格式化是否安全?像每行一个对象?否则,您必须使用每个字符的JSON字符来匹配大括号来查找对象。它可以缩进,也可以不缩进,因此我猜必须解析JSON。将返回类型更改为IEnumerableth这并不能回答我的问题,我正在寻找一种不必将JSON反序列化为对象的方法。我的问题不是收益率回归,这就是为什么它是一个评论。答案是更改您的文件。假设文件以任何方式格式化是否安全?像每行一个对象?否则,您将不得不使用每个字符的JSON字符,以匹配大括号来查找对象。它可以缩进,也可以不缩进,因此我猜必须解析JSON。