繁体   English   中英

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

[英]Unable to Deserialize data from Nested JSON List

在了解了 C# 类 Constructors 和 ArrayLists 之后来到这里,以免在这里提出一个完全愚蠢的问题:)

我正在尝试在从 API GET 调用返回的 JSON 的嵌套列表下面反序列化,如下所示:

我已经能够从empArra (字段: Emp )中获取值,但后续列表(如yearArrayprodsale )并没有返回那里的值。

你能看看下面的代码哪里做错了吗?

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":""
                }
            }
        ]
    }
]

课程

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()方法

(从 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);
                }
            }
        }
    }
}

结果

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

您的方法有两个问题:

  1. 您想为不同的 class 实例反复反序列化相同的源 ( response.Content )。 它可以反序列化为一种 object 类型:您的顶级实体。
  1. 您的数据 model 不反映您的数据。 例如YearArray应该有一个ProdSale属性,而不是它们的列表。

你有几个选择如何解决它。 给大家分享两个最常见的:

用正确的命名

您的 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>();
}

然后您需要做的就是调用以下命令:

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

现在,您的结果将填充所有数据。

使用JsonProperty

如果您不想在您的域 model 中使用相同的名称(在 json 中使用),那么您可以通过JsonProperty属性定义这两个世界之间的映射。

现在您的域 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>();
}

用法将完全相同:

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

更新:如何显示数据

在控制台应用程序中表示层次结构可以通过多种方式实现。 这里我将使用缩进。 我介绍了以下微小的辅助方法:

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

有了这个,数据可视化可以通过以下方式实现:

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

打印的 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