我有我试图以提取特定对象解析一个巨大的JSON文件(几十对象千元,> 100 MB的文件)。由于该文件是这么大,我想只反序列化特定的一部分,我需要(如果可能的话,那是),而无需反序列化整个文件。
该目的应该基于包含在每个对象特定属性"arena_id":xxxxx
,被格式化这样的对象(精简版)的价值发现:
{"object":"card","id":"61a908e8-6952-46c0-94ec-3962b7a4caef","oracle_id":"e70f5520-1b9c-4351-8484-30f0dc692e01","multiverse_ids":[460007],"mtgo_id":71000,"arena_id":69421}
为了反序列化整个文件我写了下面的代码:
public static RootObject GetCardFromBulkScryfall()
{
string s = null;
using (StreamReader streamReader = new StreamReader(Path.Combine(GetAppDataPath(), @"scryfall-default-cards.json")))
{
s = streamReader.ReadToEnd();
}
RootObject card = JsonConvert.DeserializeObject<RootObject>(s);
return card;
}
我甚至不知道我想要做的是可能的,但如果它不是我的问题是什么来处理一个文件,这个大,而无需反序列化整个最好的办法。
使用JsonTextReader与JsonTextWriter枚举对象,然后反序列化他们,如果他们的财产也需要值。
这段代码使用的内存,我的电脑上112MB JSON文件工作16MB。
让我知道,如果你有问题或需要修复。
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
string jsonFilePath = "1.json";
string propName = "arena_id";
RootObject[] objects = SearchObjectsWithProperty<RootObject, int>(jsonFilePath, propName, 69421, CancellationToken.None).ToArray();
System.Diagnostics.Debugger.Break();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
System.Diagnostics.Debugger.Break();
}
}
static IEnumerable<T> SearchObjectsWithProperty<T, V>(string jsonFilePath, string propName, V propValue, CancellationToken cancellationToken) where V : IEquatable<V>
{
using (TextReader tr = File.OpenText(jsonFilePath))
{
using (JsonTextReader jr = new JsonTextReader(tr))
{
StringBuilder currentObjectJson = new StringBuilder();
while (jr.Read())
{
cancellationToken.ThrowIfCancellationRequested();
if (jr.TokenType == JsonToken.StartObject)
{
currentObjectJson.Clear();
using (TextWriter tw = new StringWriter(currentObjectJson))
{
using (JsonTextWriter jw = new JsonTextWriter(tw))
{
jw.WriteToken(jr);
string currObjJson = currentObjectJson.ToString();
JObject obj = JObject.Parse(currObjJson);
if (obj[propName].ToObject<V>().Equals(propValue))
yield return obj.ToObject<T>();
}
}
}
}
}
}
}
}
public class RootObject
{
public string @object { get; set; }
public string id { get; set; }
public string oracle_id { get; set; }
public int[] multiverse_ids { get; set; }
public int mtgo_id { get; set; }
public int arena_id { get; set; }
}
}
如果你不关心的内存,但速度快,有一个快速和简单的解析器在C翻译++的回答了我的第一个问题,但它有树一样的输出,它是缺失的,除了印刷和调试/浏览对象的任何功能(VisualNode3 )。