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

32

我从一个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"]
}

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

    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被反序列化了。

这应该很简单,但出于某种原因我无法确定正确的对象表示方法。

3个回答

34

使用此网站进行表示:

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);

3
Item322A和Item2B不是常量。但感谢您的回答。 - user3574076
5
作为对任何感兴趣的人的后续说明。如果您使用Visual Studio,则可以使用“特殊粘贴”功能。基本上可以执行此答案中链接网站相同的操作。同样适用于XML。 - user3574076

25

对于 "Items" 使用一个 Dictionary<string, List<Info>>,即:

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


很酷,我要试试这个。我刚刚尝试了类似的方法,但是把字典包装在列表中了! - user3574076
这个起作用了。原来我上次的尝试是非常接近的。 - user3574076

6
您可以使用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);
}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接