简体   繁体   English

无法反序列化嵌套 JSON 列表中的数据

[英]Unable to Deserialize data from Nested JSON List

Coming here after learning about C# classes Constructors and ArrayLists so that not to put a completely dumb question here:)在了解了 C# 类 Constructors 和 ArrayLists 之后来到这里,以免在这里提出一个完全愚蠢的问题:)

I'm trying to Deserialize below Nested Lists of JSON returned from an API GET call as below:我正在尝试在从 API GET 调用返回的 JSON 的嵌套列表下面反序列化,如下所示:

I've been able to get the value from the empArra (Field: Emp ), but subsequent lists like yearArray , prod and sale are not returning there values.我已经能够从empArra (字段: Emp )中获取值,但后续列表(如yearArrayprodsale )并没有返回那里的值。

Can you please look into the below code that where is it doing wrong?你能看看下面的代码哪里做错了吗?

JSON JSON

 [
    {
        "employee":"156718100",
        "availability":[
            {
                "year":2018,
                "sales":{
                    "availability":"Maybe",
                    "reason":""
                },
                "prod":{
                    "availability":"Maybe",
                    "reason":""
                }
            },
            {
                "year":2019,
                "sales":{
                    "availability":"Maybe",
                    "reason":""
                },
                "prod":{
                    "availability":"Maybe",
                    "reason":""
                }
            },
            {
                "year":2020,
                "sales":{
                    "availability":"Maybe",
                    "reason":""
                },
                "top":{
                    "availability":"Maybe",
                    "reason":""
                }
            },
            {
                "year":2021,
                "sales":{
                    "availability":"Maybe",
                    "reason":""
                },
                "prod":{
                    "availability":"Maybe",
                    "reason":""
                }
            }
        ]
    }
]

Classes课程

public class sale
{
    public string SaleAvailability { get; set; }
    public string SaleReason { get; set; }
    
    public sale(string pSaleAvailability, string pSaleReason)
    {
        this.SaleAvailability = pSaleAvailability;
        this.SaleReason = pSaleReason;
    }
    
    public override string ToString()
    {
        return string.Format("{0} {1}", SaleAvailability, SaleReason);
    }
}

public class prod
{
    public string ProdAvailability { get; set; }
    public string ProdReason { get; set; }
    
    public prod(string pProdAvailability, string pProdReason)
    {
        this.ProdAvailability = pProdAvailability;
        this.ProdReason = pProdReason;
    }
    
    public override string ToString()
    {
        return string.Format("{0} {1}", ProdAvailability, ProdReason);
    }
}

public class yearArray
{
    public int Year { get; set; }

    public yearArray(int pYear)
    {
        this.Year = pYear;
    }

    List<sale> Sale { get; set; } = new List<sale>();
    List<prod> Prod { get; set; } = new List<prod>();
}

public class rootAvailability
{
    public List<yearArray> YearArray { get; set; } = new List<yearArray>();
}

public class empArray
{
    public string Emp { get; set; }
    public List<rootAvailability> RootAvailability { get; set; } = new List<rootAvailability>();
}

public class rootArray
{
    public List<empArray> EmpArrays { get; set; } = new List<empArray>();

}

main() method main()方法

(After getting the response from API) (从 API 获得响应后)

IRestResponse response = client.Execute<rootArray>(request);
    
//Console.WriteLine(response.Content);

List<rootArray> rootArrays = JsonConvert.DeserializeObject<List<rootArray>>(response.Content);

List<empArray> empArrays = JsonConvert.DeserializeObject<List<empArray>>(response.Content);

List<rootAvailability> rootAvailabilities = JsonConvert.DeserializeObject<List<rootAvailability>>(response.Content);

List<yearArray> yearArrays = JsonConvert.DeserializeObject<List<yearArray>>(response.Content);

List<sale> clsSale = JsonConvert.DeserializeObject<List<sale>>(response.Content);

List<prod> clsProd = JsonConvert.DeserializeObject<List<prod>>(response.Content);


foreach (var rootitem in rootArrays)
{
    foreach (var emparrayitem in empArrays)
    {
        Console.WriteLine("NSN: " + emparrayitem.Emp);
        
        foreach (var rootavailabbilitiesitem in rootAvailabilities)
        {
            
            foreach (var yearArrayItem in yearArrays)
            {
                
                Console.WriteLine("Year: " + yearArrayItem.Year);

                foreach (var saleItem in clsSale)
                {

                    Console.WriteLine("SaleAvailability: " + saleItem.SaleAvailability);
                    Console.WriteLine("SaleReason: " + saleItem.SaleReason);
                }
                foreach (var prodItem in clsProd)
                {

                    Console.WriteLine("SaleAvailability: " + prodItem.ProdAvailability);
                    Console.WriteLine("SaleReason: " + prodItem.ProdReason);
                }
            }
        }
    }
}

Results结果

Emp: 159252663
Year: 0
SaleAvailability:
SaleReason:
SaleAvailability:
SaleReason:

You have two problems with your approach:您的方法有两个问题:

  1. You want to deserialize the same source over and over again ( response.Content ) for different class instances.您想为不同的 class 实例反复反序列化相同的源 ( response.Content )。 It can be deserialized into one object type: your top level entity.它可以反序列化为一种 object 类型:您的顶级实体。
  1. Your data model does not reflect your data.您的数据 model 不反映您的数据。 For example YearArray should have a single Prod and Sale property not a list of them.例如YearArray应该有一个ProdSale属性,而不是它们的列表。

You have several options how to fix it.你有几个选择如何解决它。 Let me share with you the two most common ones:给大家分享两个最常见的:

With proper naming用正确的命名

Your object model should look like this:您的 object model 应如下所示:

public class Sale
{
    public string Availability { get; set; }
    public string Reason { get; set; }
}

public class Prod
{
    public string Availability { get; set; }
    public string Reason { get; set; }
}

public class MidLevel
{
    public int Year { get; set; }
    public Sale Sales { get; set; }
    public Prod Top { get; set; }
}

public class TopLevel
{
    public string Employee { get; set; }
    public List<MidLevel> Availability { get; set; } = new List<MidLevel>();
}

Then all you need to do is to call the following command:然后您需要做的就是调用以下命令:

var result = JsonConvert.DeserializeObject<TopLevel[]>(json);

Now, your result will be populated with all the data.现在,您的结果将填充所有数据。

With JsonProperty使用JsonProperty

If you don't want to use the same names in your domain model which is used in the json then you can define the mapping between these two worlds via JsonProperty attributes.如果您不想在您的域 model 中使用相同的名称(在 json 中使用),那么您可以通过JsonProperty属性定义这两个世界之间的映射。

Now your domain model can look like this:现在您的域 model 可以如下所示:

public class SalesInformation
{
    [JsonProperty(PropertyName = "availability")]
    public string Avail { get; set; }
    [JsonProperty(PropertyName = "reason")]
    public string Reasoning { get; set; }
}

public class ProdInformation
{
    [JsonProperty(PropertyName = "availability")]
    public string Availability { get; set; }
    [JsonProperty(PropertyName = "reason")]
    public string Reasoning { get; set; }
}

public class MidLevel
{
    [JsonProperty(PropertyName = "year")]
    public int AvailYear { get; set; }
    [JsonProperty(PropertyName = "sales")]
    public SalesInformation SalesInfos { get; set; }
    [JsonProperty(PropertyName = "top")]
    public ProdInformation ProdInfos { get; set; }
}

public class TopLevel
{
    [JsonProperty(PropertyName = "employee")]
    public string Emp { get; set; }
    [JsonProperty(PropertyName = "availability")]
    public List<MidLevel> Availabilities { get; set; } = new List<MidLevel>();
}

The usage would be exactly the same:用法将完全相同:

var result = JsonConvert.DeserializeObject<TopLevel[]>(json);

UPDATE : How to display data更新:如何显示数据

To represent hierarchy in a console application can be achieved in may ways.在控制台应用程序中表示层次结构可以通过多种方式实现。 Here I will use indentation.这里我将使用缩进。 I've introduced the following tiny helper method:我介绍了以下微小的辅助方法:

public static void WriteWithIndent(int level, string message) => Console.WriteLine("".PadLeft(level * 2) + message);

With this in hand the data visualization could be achieved in the following way:有了这个,数据可视化可以通过以下方式实现:

var result = JsonConvert.DeserializeObject<TopLevel[]>(json);
foreach (var topLevel in result)
{
    Console.WriteLine($"Employee: {topLevel.Emp}");
    foreach (var midLevel in topLevel.Availabilities)
    {
        WriteWithIndent(1, $"Year: {midLevel.AvailYear}");
        WriteWithIndent(1, "Sales:");
        WriteWithIndent(2, $"Avail: {midLevel.SalesInfos.Avail}");
        WriteWithIndent(2, $"Reason: {midLevel.SalesInfos.Reasoning}");
        WriteWithIndent(1, "Top:");
        WriteWithIndent(2, $"Avail: {midLevel.ProdInfos.Avail}");
        WriteWithIndent(2, $"Reason: {midLevel.ProdInfos.Reasoning}");
    }
}

The printed output will look like this:打印的 output 将如下所示:

Employee: 156718100
  Year: 2018
  Sales:
    Avail: Maybe
    Reason:
  Top:
    Avail: Maybe
    Reason:
  Year: 2019
  Sales:
    Avail: Maybe
    Reason:
  Top:
    Avail: Maybe
    Reason:
  Year: 2020
  Sales:
    Avail: Maybe
    Reason:
  Top:
    Avail: Maybe
    Reason:
  Year: 2021
  Sales:
    Avail: Maybe
    Reason:
  Top:
    Avail: Maybe
    Reason:

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

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