如何将JSON反序列化为正确类型的对象,而无需事先定义类型? [英] How to deserialize JSON to objects of the correct type, without having to define the type before hand?

查看:170
本文介绍了如何将JSON反序列化为正确类型的对象,而无需事先定义类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我搜索了类似的问题,但找不到与我要找的东西完全匹配的东西.

I searched through similar questions and couldn't find anything that quite matched what i was looking for.

C#的新手,请多多包涵.

New to C# so bear with me please.

我有一些要反序列化的json文件.我希望文件反序列化为正确类型的对象,而无需事先定义类型.这是我的代码:

I have some json files that i am deserializing. I want the files to deserialize to objects of the correct type, without having to define the type before hand. Here's my code:

public class loadJson
    {
        //path of the file location
        public void readJson(string path)
        {
            //array of files at the path location. right now just reading one file
            FileInfo[] files = new DirectoryInfo(path).GetFiles("seleniumExample.json").ToArray();

            foreach (FileInfo fi in files)
            {

                dynamic b1 = null;
                using (StreamReader file = new StreamReader(fi.FullName))
                {

                    string fileText = file.ReadToEnd();
                    //Console.WriteLine(fileText);

                    try
                    {
                        b1 = Newtonsoft.Json.JsonConvert.DeserializeObject(fileText);
                    }
                    catch(Exception e)
                    {
                        Console.WriteLine("ERROR!!!! " + e.ToString());
                    }

                    file.Close();
                }
            }
        }
    }

我有一堆对象类型,这些对象类型将通过json文件输入到程序中.

I have a bunch of object types that I will be feeding into my program through json files.

我不想显式地将b1称为Bid,Client或任何其他特定的预定义类.如果我确实明确地将b1称为Bid,它会很好地加载所有信息并填写正确的实例变量.

I don't want to have to explicitly call b1 a Bid, or a Client, or any other specific predefined class. If I do explicitly call b1 a Bid, it loads all the info just fine and fills out the correct instance variables.

但是当我使用动态"或通用的对象"时,它无法弄清楚,而只是初始化为对象".

But when I use "dynamic", or general "object", it can't figure it out and just initializes to an "object".

是否可以执行通用反序列化,并使其基于json文件中定义的字段创建正确类的对象?

Is there a way to perform generic deserialization and have it create an object of the correct class based on the fields defined in the json file?

预先感谢您的帮助,如果我的问题非常不清楚,我深表歉意.如果是这样,请让我知道我如何可以帮助您消除任何歧义.再次感谢.

Thanks in advance for the help, and i apologize if my question is incredibly unclear. If so, please just let me know how I can help clear up any ambiguity. Thanks again.

推荐答案

通过使用的合成属性,例如:

Json.NET has the ability to record the .Net object type of polymorphic types during serialization, by using the setting TypeNameHandling = TypeNameHandling.Auto. When the setting is enabled the .Net type of polymorphic objects will appear as a synthetic property called "$type", for instance:

"$type": "Newtonsoft.Json.Samples.Stockholder, Newtonsoft.Json.Tests"

但是,如果调用常规方法属性/M_Newtonsoft_Json_JsonConvert_SerializeObject.htm"rel =" noreferrer> JsonConvert.SerializeObject(Object) JsonSerializer.Serialize(TextWriter, Object) .相反,您必须使用一种接受期望的"根类型的序列化方法之一,例如 JsonSerializer.Serialize(TextWriter, Object, Type) .传递typeof(object)作为期望的类型可以保证type属性将出现:

However, the "$type" property is never emitted for the root object if you call the conventional methods JsonConvert.SerializeObject(Object) or JsonSerializer.Serialize(TextWriter, Object). Instead, you must use one of the serialization methods that accepts an "expected" root type, for instance SerializeObject(Object, Type, JsonSerializerSettings) or JsonSerializer.Serialize(TextWriter, Object, Type). Passing typeof(object) as the expected type guarantees the type property will appear:

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
var json = JsonConvert.SerializeObject(rootObject, typeof(object), settings);

如果使用此设置创建JSON文件,则JSON本身将记住序列化对象的类型.只要您将set TypeNameHandling设置为 TypeNameHandling.None .例如:

If you create your JSON files using this setting, the JSON itself will remember the type of object serialized. This type will be used by Json.NET during deserialization, as long as you use set TypeNameHandling to something other than TypeNameHandling.None. e.g.:

var settings = new Newtonsoft.Json.JsonSerializerSettings { TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto };
b1 = Newtonsoft.Json.JsonConvert.DeserializeObject(fileText, settings);

工作示例.Net小提琴此处.

Working sample .Net fiddle here.

注意事项:这种用JSON存储.Net类型的方法是非标准的.其他序列化程序,例如 DataContractJsonSerializer 不要以这种格式处理类型信息.

Caveats: this way of storing .Net types in JSON is nonstandard. Other serializers such as DataContractJsonSerializer do not process type information in this format.

还请注意 Newtonsoft文档:

当您的应用程序从外部源反序列化JSON时,应谨慎使用

TypeNameHandling.反序列化除None以外的其他值时,应使用自定义SerializationBinder验证传入的类型.

TypeNameHandling should be used with caution when your application deserializes JSON from an external source. Incoming types should be validated with a custom SerializationBinder when deserializing with a value other than None.

有关为何可能需要这样做的讨论,请参见 Newtonsoft Json中的TypeNameHandling警告

For a discussion of why this may be necessary, see TypeNameHandling caution in Newtonsoft Json, How to configure Json.NET to create a vulnerable web API, and Alvaro Muñoz & Oleksandr Mirosh's blackhat paper https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf.

这篇关于如何将JSON反序列化为正确类型的对象,而无需事先定义类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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