简体   繁体   English

Json 到 C# 对象处理动态属性

[英]Json to C# object handling dynamic properties

I am trying to implement the json structure in c# objects and I am trying to understand how I can use the correct object depending on the type.我正在尝试在 c# 对象中实现 json 结构,并且我试图了解如何根据类型使用正确的对象。 For example:例如:

public class RootObject
{
    public string name { get; set; }
    public Content content { get; set; }

}
public class Content
{
    public string id{ get; set; }
    public string type { get; set; }
    public Dictionary<string, Item> child { get; set; }
}

public class Item
{
    public string id { get; set; }
    public string type { get; set; }
    public List<string> model { get; set;}
    public string[] color {get; set;}
}

Please note this is just an example there are more properties for each object.请注意,这只是一个示例,每个对象都有更多属性。 If Json contains type = "Boy" how can I generate the boy object.如果 Json 包含 type = "Boy" 我如何生成男孩对象。

Example JSON:示例 JSON:

string json = @"
            {
            'name': 'Object 1',
            'content': {
                'body': {
                    'id': 'body',
                    'type': 'Body'
                },
                'style': {
                    'id': 'style',
                    'type': 'Style'
                },
                'DynamicName-123': {
                    'id': 'DynamicName-123',
                    'type': 'Row'
                    'model': {},
                    'colors': []
                },
                'DynamicName-434': {
                    'id': 'DynamicName-434',
                    'type': 'Column'
                    'model': {},
                    'colors': []
                },
                'DynamicName-223': {
                    'id': 'DynamicName-223',
                    'type': 'Item'
                    'model': {},
                    'colors': []
                }
            }
        }";

If your key/value pair are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData] Read more如果您的键/值对不是固定的并且数据必须是可配置的,那么 Newtonsoft.json 有一个可以在这里使用的功能,那就是[JsonExtensionData] 阅读更多

Extension data is now written when an object is serialized.现在在对象序列化时写入扩展数据。 Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you're deserializing to.读取和写入扩展数据使自动往返所有 JSON 成为可能,而无需将每个属性添加到您要反序列化的 .NET 类型。 Only declare the properties you're interested in and let extension data do the rest.只声明您感兴趣的属性,让扩展数据完成其余的工作。

In your case, suppose there is a class,在你的情况下,假设有一个类,

public class MyClass
{
    public string Qaz { get; set; }
    public string Wsx { get; set; }

    [JsonExtensionData]
    public Dictionary<string, JToken> child { get; set; }

    public MyClass()
    {
        child = new Dictionary<string, JToken>();
    }
}

In the above class, you know that Qaz and Wsx are always present from your json either they contain value or null,在上面的课程中,您知道QazWsx始终存在于您的 json 中,它们包含值或空值,

But for dynamic data, you can't say which key/value pair you will receive from your json so the [JsonExtensionData] can collect all those key/value pair in a dictionary.但是对于动态数据,您无法说出将从 json 中收到哪个键/值对,因此[JsonExtensionData]可以在字典中收集所有这些键/值对。

Suppose the below classes will be for your dynamic data,假设以下类将用于您的动态数据,

public class ABC
{
    public string Abc { get; set; }
}

public class PQR
{
    public string Pqr { get; set; }
}

public class XYZ
{
    public string Xyz { get; set; }
}

Serialization:序列化:

ABC aBC = new ABC { Abc = "abc" };
PQR pQR = new PQR { Pqr = "pqr" };
XYZ xYZ = new XYZ { Xyz = "xyz" };

MyClass myClass = new MyClass();

myClass.Qaz = "qaz";
myClass.Wsx = "wsx";

myClass.child.Add("ABC", JToken.FromObject(aBC));
myClass.child.Add("PQR", JToken.FromObject(pQR));
myClass.child.Add("XYZ", JToken.FromObject(xYZ));

string outputJson = JsonConvert.SerializeObject(myClass);

This will give you json like这会给你 json 像

{
  "Qaz": "qaz",
  "Wsx": "wsx",
  "ABC": {
    "Abc": "abc"
  },
  "PQR": {
    "Pqr": "pqr"
  },
  "XYZ": {
    "Xyz": "xyz"
  }
}

Deserialization:反序列化:

MyClass myClass = JsonConvert.DeserializeObject<MyClass>(outputJson);

string Qaz = myClass.Qaz;
string Wsx = myClass.Wsx;

if (myClass.child.ContainsKey("ABC"))
{
    ABC abcObj = myClass.child["ABC"].ToObject<ABC>();
}

if (myClass.child.ContainsKey("PQR"))
{
    PQR pqrObj = myClass.child["PQR"].ToObject<PQR>();
}

if (myClass.child.ContainsKey("XYZ"))
{
    XYZ pqrObj = myClass.child["XYZ"].ToObject<XYZ>();
}

Conclusion: The main aim of [JsonExtensionData] is to keep your json class hierarchy simple and more readable so you don't need to manage class structure for every property.结论: [JsonExtensionData]的主要目的是让您的 json 类层次结构简单且更具可读性,因此您无需为每个属性管理类结构。

Get all dynamic data with the specific key in JToken inside Dictionary :使用 Dictionary 中 JToken 中的特定键获取所有动态数据:

You can use LINQ to fetch all dynamic data of particular key from the above dictionary.您可以使用 LINQ 从上述字典中获取特定键的所有动态数据。

var allAbcTypes = myClass.child
    .SelectMany(x => x.Value
                      .ToObject<JObject>()
                      .Properties()
                      .Where(p => p.Name == "Abc")    //<= Use "Column" instead of "Abc"
                      .Select(o => new ABC            //<= Use your type that contais "Column" as a property
                      {
                           Abc = o.Value.ToString()
                      })).ToList();

In your case, Its something like,在你的情况下,它就像,

var allColumnTypes = myClass.child
    .SelectMany(x => x.Value
                      .ToObject<JObject>()
                      .Properties()
                      .Where(p => p.Name == "Column")
                      .Select(o => new Item
                      {
                         id = x.Value["id "].ToString(),
                         type = x.Value["type "].ToString(),
                         model = x.Value["model"].ToObject<List<string>>(),
                         color = x.Value["color"].ToObject<string[]>()
                      })).ToList();

如果要反序列化为带有 Key 字符串和动态值(在这种情况下是男孩或女孩)的字典,我知道的唯一方法是使用 Dynamic 类:

 public List<Dictionary<string, dynamic>> child { get; set; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM