gpt4 book ai didi

c# - 使用 Json.NET 从 WebService 反序列化大型 json

转载 作者:行者123 更新时间:2023-12-04 07:38:43 24 4
gpt4 key购买 nike

我从 WebService 接收到一个大的 JSON 字符串,我正在寻找使用 C# 反序列化它的最佳内存优化方法。
JSON结构:

{
"d": {
"results": [
{
"metadata": {
"id": "",
"uri": "",
"type": ""
},
"ID": "",
"Value1": "",
"Value2": "",
"Value3": ""
},
{
"metadata": {
"id": "",
"uri": "",
"type": ""
},
"ID": "",
"Value1": "",
"Value2": "",
"Value3": ""
},
]
}
}
我想获取“结果”数组中的所有对象,但只有一个对象一个接一个,而不像现在的完整列表。
我已经在使用 StreamReader 来避免将完整的 json 字符串加载到内存中。
是否有任何选项可以只读取一个对象,进行一些处理然后读取下一个对象以避免“OutOfMemoryExceptions”?
WebResponse response = r.GetResponse();  
using (Stream dataStream = response.GetResponseStream())
{
var serializer = new JsonSerializer();

using (var sr = new StreamReader(dataStream))
using (var jsonTextReader = new JsonTextReader(sr))
{
return ((RootObject)serializer.Deserialize<RootObject>(jsonTextReader)).RootObject2.Results;
}

最佳答案

你可以做的是采用Issues parsing a 1GB json file using JSON.NET的基本方法。和 Deserialize json array stream one item at a time ,也就是通过JSON进行流式处理,反序列化和yield返回每个对象;但另外应用一些状态过滤表达式仅反序列化 StartObject与路径匹配的标记 d.results[*] .
为此,首先定义以下接口(interface)和扩展方法:

public interface IJsonReaderFilter
{
public bool ShouldDeserializeToken(JsonReader reader);
}

public static class JsonExtensions
{
public static IEnumerable<T> DeserializeSelectedTokens<T>(Stream stream, IJsonReaderFilter filter, JsonSerializerSettings settings = null, bool leaveOpen = false)
{
using (var sr = new StreamReader(stream, leaveOpen : leaveOpen))
using (var reader = new JsonTextReader(sr))
foreach (var item in DeserializeSelectedTokens<T>(reader, filter, settings))
yield return item;
}

public static IEnumerable<T> DeserializeSelectedTokens<T>(JsonReader reader, IJsonReaderFilter filter, JsonSerializerSettings settings = null)
{
var serializer = JsonSerializer.CreateDefault(settings);
while (reader.Read())
if (filter.ShouldDeserializeToken(reader))
yield return serializer.Deserialize<T>(reader);
}
}
现在,只过滤那些匹配路径 d.results[*] 的项目,定义以下过滤器:
class ResultsFilter : IJsonReaderFilter
{
const string path = "d.results";
const int pathDepth = 2;
bool inArray = false;

public bool ShouldDeserializeToken(JsonReader reader)
{
if (!inArray && reader.Depth == pathDepth && reader.TokenType == JsonToken.StartArray && string.Equals(reader.Path, "d.results", StringComparison.OrdinalIgnoreCase))
{
inArray = true;
return false;
}
else if (inArray && reader.Depth == pathDepth + 1 && reader.TokenType == JsonToken.StartObject)
return true;
else if (inArray && reader.Depth == pathDepth && reader.TokenType == JsonToken.EndArray)
{
inArray = false;
return false;
}
else
{
return false;
}
}
}
接下来,为每个结果创建以下数据模型:
public class Metadata
{
public string id { get; set; }
public string uri { get; set; }
public string type { get; set; }
}

public class Result
{
public Metadata metadata { get; set; }
public string ID { get; set; }
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
}
现在您可以按如下方式逐步反序列化您的 JSON 流:
foreach (var result in JsonExtensions.DeserializeSelectedTokens<Result>(dataStream, new ResultsFilter()))
{
// Process each result in some manner.
result.Dump();
}
演示 fiddle here .

关于c# - 使用 Json.NET 从 WebService 反序列化大型 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67608176/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com