如何控制大阵异质物体的反序列化的JSON.net [英] How to control deserialization of large array of heterogenous objects in JSON.net

查看:113
本文介绍了如何控制大阵异质物体的反序列化的JSON.net的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用JSON作为中间格式的旧properietary对象数据库格式迁移数据。对象输出到一个JSON数组的对象,每一个都具有一个初始字段给出原始对象随后字段称为实例具有嵌套原始对象的类型。



我需要因为有潜在的成千上万人以流这些 - 我不能仅仅读取整个JSON数组到内存中,然后再处理它。



因此,JSON是这样的:

  [
{
类型:富,
实例:{的
//例如美孚类型
}
},
{
类型:酒吧,
实例:
},
//几十或多个对象的数十万...
] $ b $ {栏中键入

//实例} b

使用Json.NET,什么是最好的方式在同一时间在一个数组元素流,访问类型 ?属性,然后反序列化实例到相应类型的.NET对象



编辑:虽然有关于读取大JSON数组,具体情况类似的问题的访问实例这个问题不回答。


解决方案

答案放在一起,以





多态性反序列化JSON类,而类型信息

首先,假设你有一个自定义的 SerializationBinder (或类似的东西),将地图类型名称类型。





<:>接下来,您可以通过顶级对象在流JSON数据(行走的的顶级数组)具有以下扩展方法枚举pre> 公共静态类JsonExtensions
{
公共静态的IEnumerable< JObject> WalkObjects(的TextReader的TextReader)
{
使用(JsonTextReader读卡器=新JsonTextReader(TextReader的))
{
,而(reader.Read())
{
如果(reader.TokenType == JsonToken.StartObject)
{
JObject OBJ = JObject.Load(读卡器);
如果(OBJ!= NULL)
{
收益回报的obj;
}
}
}
}
}
}

然后,假设你有一些阅读您的JSON数据,可以流中的JSON和转换顶层数组元素one一个用于处理如下:

  SerializationBinder粘结剂=新MyBinder(); //你的定制绑定。 
使用使用(VAR流= GetStream(JSON))
(VAR读者=新的StreamReader(流Encoding.Unicode))
{
变种的AssemblyName = System.Reflection.Assembly 。.GetExecutingAssembly()的GetName()名称。
VAR项目=从OBJ在JsonExtensions.WalkObjects(阅读器)
让jtype的OBJ = [型]
让jInstance的obj = [实例]
,其中jtype的!=空&功放;&安培; jType.Type == JTokenType.String
,其中jInstance = NULL&放大器;!&安培; !jInstance.Type == JTokenType.Object
型让利= binder.BindToType(的AssemblyName,(串)jtype的)
,其中类型= NULL
选择jInstance.ToObject(类型); //反序列化到绑定的类型!

的foreach(在项目VAR项目)
{
//处理每个项目。
的Debug.WriteLine(JsonConvert.SerializeObject(项目));
}
}


I'm migrating data from an old properietary object database format using JSON as the intermediate format. The objects are output into a JSON array of objects, each of which has an initial field giving the type of the original object followed by field called Instance which has the nested original object.

I need to stream these in as there are potentially hundreds of thousands of them - I can't just read the whole JSON array into memory and then process it.

So the JSON looks like this:

[
{
    "Type": "Foo",
    "Instance": {
        // instance of Foo type
    }
},
{
    "Type": "Bar",
    "Instance": {
        // instance of Bar type
    }
},
// tens or hundreds of thousands more objects...
]

Using Json.NET, what's the best way to stream in one array element at a time, access the "Type" property and then deserialize the "Instance" to a .Net object of the appropriate type?

Edit: although there is a similar question regarding reading a large JSON array, the specifics of accessing the instance are not answered in that question.

解决方案

Putting together answers to

First, assume you have a custom SerializationBinder (or something similar) that will map type names to types.

Next, you can enumerate through the top-level objects in streaming JSON data (walking into top-level arrays) with the following extension method:

public static class JsonExtensions
{
    public static IEnumerable<JObject> WalkObjects(TextReader textReader)
    {
        using (JsonTextReader reader = new JsonTextReader(textReader))
        {
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.StartObject)
                {
                    JObject obj = JObject.Load(reader);
                    if (obj != null)
                    {
                        yield return obj;
                    }
                }
            }
        }
    }
}

Then, assuming you have some stream for reading your JSON data, you can stream the JSON in and convert top-level array elements one by one for processing as follows:

        SerializationBinder binder = new MyBinder(); // Your custom binder.
        using (var stream = GetStream(json))
        using (var reader = new StreamReader(stream, Encoding.Unicode))
        {
            var assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
            var items = from obj in JsonExtensions.WalkObjects(reader)
                        let jType = obj["Type"]
                        let jInstance = obj["Instance"]
                        where jType != null && jType.Type == JTokenType.String
                        where jInstance != null && jInstance.Type == JTokenType.Object
                        let type = binder.BindToType(assemblyName, (string)jType)
                        where type != null
                        select jInstance.ToObject(type); // Deserialize to bound type!

            foreach (var item in items)
            {
                // Handle each item.
                Debug.WriteLine(JsonConvert.SerializeObject(item));
            }
        }

这篇关于如何控制大阵异质物体的反序列化的JSON.net的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆