将嵌套的 JSON 反序列化为 C# 对象

Posted

技术标签:

【中文标题】将嵌套的 JSON 反序列化为 C# 对象【英文标题】:Deserialize nested JSON into C# objects 【发布时间】:2016-12-12 02:24:38 【问题描述】:

我从如下所示的 API 获取 JSON:


  "Items": 
    "Item322A": [
      "prop1": "string",
      "prop2": "string",
      "prop3": 1,
      "prop4": false
    ,
      "prop1": "string",
      "prop2": "string",
      "prop3": 0,
      "prop4": false
    ],
       "Item2B": [
      "prop1": "string",
      "prop2": "string",
      "prop3": 14,
      "prop4": true
    ]
  ,
  "Errors": ["String"]

我已经尝试了几种方法来在 c# 对象中表示这个 JSON(这里列出的太多了)。我尝试过使用列表和字典,这是我最近尝试表示的示例:

    private class Response
    
        public Item Items  get; set; 
        public string[] Errors  get; set; 
    

    private class Item
    
        public List<SubItem> SubItems  get; set; 
    

    private class SubItem
    
        public List<Info> Infos  get; set; 
    

    private class Info
    
        public string Prop1  get; set; 
        public string Prop2  get; set; 
        public int Prop3  get; set; 
        public bool Prop4  get; set; 
    

这是我用来反序列化 JSON 的方法:

    using (var sr = new StringReader(responseJSON))
    using (var jr = new JsonTextReader(sr))
    
        var serial = new JsonSerializer();
        serial.Formatting = Formatting.Indented;
        var obj = serial.Deserialize<Response>(jr);
    

obj 包含 ItemsErrors。而Items 包含SubItems,但SubItemsnull。因此,除了Errors 之外,实际上没有任何东西被反序列化。

应该很简单,但由于某种原因我无法找出正确的对象表示

【问题讨论】:

【参考方案1】:

使用此站点进行表示:

https://quicktype.io/csharp/

这样的事情可能会对你有所帮助

public class Item322A

    public string prop1  get; set; 
    public string prop2  get; set; 
    public int prop3  get; set; 
    public bool prop4  get; set; 


public class Item2B

    public string prop1  get; set; 
    public string prop2  get; set; 
    public int prop3  get; set; 
    public bool prop4  get; set; 


public class Items

    public List<Item322A> Item322A  get; set; 
    public List<Item2B> Item2B  get; set; 


public class jsonObject

    public Items Items  get; set; 
    public List<string> Errors  get; set; 

这里是如何反序列化(使用 JsonConvert 类):

jsonObject ourlisting = JsonConvert.DeserializeObject<jsonObject>(strJSON);

【讨论】:

Item322A 和 Item2B 不是常量。不过谢谢你的回答 作为对此感兴趣的任何人的后续行动。如果您使用 Visual Studio,则可以使用“选择性粘贴”功能。并且基本上与此答案中的链接站点相同。也适用于 XML【参考方案2】:

对于"Items",使用Dictionary&lt;string, List&lt;Info&gt;&gt;,即:

class Response

    public Dictionary<string, List<Info>> Items  get; set; 
    public string[] Errors  get; set; 


class Info

    public string Prop1  get; set; 
    public string Prop2  get; set; 
    public int Prop3  get; set; 
    public bool Prop4  get; set; 

这假定项目名称 "Item322A""Item2B" 会因响应而异,并将这些名称作为字典键读取。

示例fiddle。

【讨论】:

酷,我要试试这个。我只是尝试了一种类似的方法,但是将字典包含在一个列表中! 这行得通。原来我的最后一次尝试是如此接近【参考方案3】:

您可以使用Json.Parse 来查询数据——并且只使用单个模型。

private class Info

    public string Prop1  get; set; 
    public string Prop2  get; set; 
    public int Prop3  get; set; 
    public bool Prop4  get; set; 


var result = JObject.Parse(resultContent);   //parses entire stream into JObject, from which you can use to query the bits you need.
var items = result["Items"].Children().ToList();   //Get the sections you need and save as enumerable (will be in the form of JTokens)

List<Info> infoList = new List<Info>();  //init new list to store the objects.

//iterate through the list and match to an object. If Property names don't match -- you could also map the properties individually. Also useful if you need to dig out nested properties.
foreach(var subItem in items)
foreach(JToken result in subItem)
Info info = result.ToObject<Info>();
infoList.add(info);

【讨论】:

以上是关于将嵌套的 JSON 反序列化为 C# 对象的主要内容,如果未能解决你的问题,请参考以下文章

将JSON对象反序列化为嵌套的C#对象

如何将具有嵌套属性的 JSON 对象反序列化为 Symfony 实体?

Json.NET:将嵌套数组反序列化为强类型对象

System.Text.Json - 将嵌套对象反序列化为字符串

Json.NET:反序列化嵌套字典

将 JSON 字符串反序列化为多个 C# 对象