如何分析不反序列化JSON整个文件只特定的对象?

问题描述 投票:0回答:2

我有我试图以提取特定对象解析一个巨大的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;
    }

我甚至不知道我想要做的是可能的,但如果它不是我的问题是什么来处理一个文件,这个大,而无需反序列化整个最好的办法。

c# json json.net json-deserialization
2个回答
3
投票

使用JsonTextReaderJsonTextWriter枚举对象,然后反序列化他们,如果他们的财产也需要值。

这段代码使用的内存,我的电脑上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; }
    }
}

1
投票

如果你不关心的内存,但速度快,有一个快速和简单的解析器在C翻译++的回答了我的第一个问题,但它有树一样的输出,它是缺失的,除了印刷和调试/浏览对象的任何功能(VisualNode3 )。

Way to read (or edit) big JSON from / to stream

© www.soinside.com 2019 - 2024. All rights reserved.