【问题标题】:Deserialize nested JSON into C# class将嵌套的 JSON 反序列化为 C# 类
【发布时间】:2018-09-12 20:44:52
【问题描述】:

我有一个这样的 JSON 类

{
    "Items": {
        "Item_1A": {
            "prop1": "string",
            "prop2": "string",
            "prop3": 1,
            "prop4": [{
                "prop_x": 100
            },
            {
                "prop_y": 200
            }]
        },
        "Item2B": {
            "prop1": "string",
            "prop2": "string",
            "prop3": 14,
            "prop4": [{
                "prop_z": 300
            }]
        }
    }
}

我怎样才能使它成为 C# 类?这是我目前所拥有的:

public class Info
{
    public string prop1 {get;set;}
    public string prop2 {get;set;}
    public int prop3 {get;set;}
    public Dictionary<string, List<int>> prop4 {get;set;}
}
public class Response
{
    public Dictionary<string, List<Info>> Item {get;set;}
}

我尝试点击此链接,但没有成功 Deserialize nested JSON into C# objects

【问题讨论】:

  • 你已经尝试了什么?什么具体不起作用?
  • 我不确定这是不是有效的 JSON,"int" 应该用引号引起来。
  • 我找到了链接,然后我使用了 Dictionnary> 但它只返回了 null。
  • 我认为 JSON 格式不正确。 "prop_y": int之后的方括号后面不能有逗号
  • 我的错,我刚刚编辑了

标签: c# json serialization


【解决方案1】:

你的数据模型应该如下:

public class Info
{
    public string prop1 {get;set;}
    public string prop2 {get;set;}
    public int prop3 {get;set;}
    // Modified from 
    //public Dictionary<string, List<int>> prop4 {get;set}
    public List<Dictionary<string, int>> prop4 {get;set;}
}

public class Response
{
    // Modified from 
    //public class Dictionary<string, List<Info>> Item {get;set;}
    public Dictionary<string, Info> Items {get;set;}
}

注意事项:

  • Response.Item 应该被命名为 Items

  • 在您的 JSON 中,"Items" 是一个具有可变名称对象值属性的对象:

    {
        "Items": {
            "Item_1A": { },
            "Item2B": { }
        }
    }
    

    对于适当的非集合类型T,应将其建模为Dictionary&lt;string, T&gt;。假设您使用的是,请参阅Serialization Guide: Dictionaries 了解详情。如果不是, 的行为类似。

    您的数据模型 public class Dictionary&lt;string, List&lt;Info&gt;&gt; Items 本来适用于具有可变名称 array-valued 属性的对象:

    {
        "Items": {
            "Item_1A": [{ },{ }],
            "Item2B": [{ }]
        }
    }
    

    但这不是你所拥有的。

  • 同时"prop4" 是一个数组,其中包含具有可变命名的对象值属性的对象,例如:

    "prop4": [ // Outer container is an array
      {        // Inner container is an object
        "prop_x": 100
      },
      {
        "prop_y": 200
      }
    ]
    

    因此,List&lt;T&gt; 之类的集合应该用作 outer 泛型类型:

    public List<Dictionary<string, int>> prop4 {get;set;}
    

    Serialization Guide: IEnumerable, Lists, and Arrays

  • 如您所见,How to auto-generate a C# class file from a JSON object string 中提到的代码生成工具通常无法识别具有可变属性名称的 JSON 对象。在这种情况下,自动生成的类可能需要手动替换为包含类型中的适当 Dictionary&lt;string, T&gt; 属性。

示例工作小提琴here

【讨论】:

    【解决方案2】:

    以下是在 json 之后创建代理类的提示:

    首先,要确保它是有效的 JSON,请访问此网站并运行验证器:https://jsonlint.com/

    如果可以的话,有一些工具可以直接将json和xml转换为c#代理类:http://json2csharp.com/:https://xmltocsharp.azurewebsites.net/

    现在你去吧!只需将它们复制到您的模型并开始使用它。

    【讨论】:

    • 我知道转换器,但我的 JSON 文件最多可以包含数千个数据。这个问题就像 2 个键的样本,如果我有 20000 个键怎么办?那个转换器怎么做?我之所以这么问,是因为我在上面发布的链接中有一个类似的问题,解决方案是 Dictionary,但是当我使用我的时,我就是无法让它工作。
    • 它们是不同的键值,你知道吗?或者您在 cmets 之前从未阅读过我上面提供的所有信息?检查我发布的问题链接怎么样?
    【解决方案3】:

    只是对您的模型进行了一些小改动。你的 prop4 是一个列表或数组。

    public class Info
    {
      public string prop1 {get;set;}
      public string prop2 {get;set;}
      public int prop3 {get;set;}
      public List<Dictionary<string, List<int>>> prop4 {get;set}
    }
    public class  Response
    {
      public class Dictionary<string, Info> Items {get;set;} // Should be named Items
    }
    

    【讨论】:

    【解决方案4】:

    您的prop4Dictionary&lt;string, List&lt;int&gt;&gt;,在序列化时看起来像这样(为简洁起见,我在发出的JSON 中省略了$type 属性):

    {
       "X": {
          "$values": [ 1, 2 ]
       },
       "Y": {
          "$values": [ 3, 4 ]
       }    
    }
    

    您的 JSON 虽然格式正确,但“形状”错误。它看起来更像是一个包含一个项目的字典的数组。

    在上面的 JSON 中,XY 是字典中的键,是用 JSON 建模的“常规对象”。 $values 表示每个键的整数列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-12
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      • 2018-03-20
      • 2020-09-29
      相关资源
      最近更新 更多