无法在 C# 中反序列化嵌套 JSON

Cannot Deserialize Nested JSON in C#

我是编程和 C# 的新手。我正在使用 Visual Studio(最新)编写我的应用程序。

这是一个试图读取日志(文本)文件的控制台应用程序,其中每一行都是一个单独的 JSON 条目。

这是单个项目 JSON 条目的样子:

{
    "timestamp": "2022-02-09T07:05:59Z",
    "event": "Color",
    "Hex": "#FFFF00",
    "Name": "Yellow"
}

我建立了文本文件的完整路径并将其存储在字符串 'fileFullPath' 中,我是 'using System.Text.Json'。

文本文件中的每个条目总是有两个字段 - 'timestamp' 和 'event'。我创建了一个名为 'LogHeader':

的基础 class
namespace LogModels
{
    public class LogHeader
    {
        public string TimeStamp { get; set; }
        public string Event { get; set; }

    }
}

然后,我为每个事件创建了一个class并继承自LogHeader:

public class Color : LogHeader
{
  public string Hex { get; set;}
  public string Name { get; set;}
}

接下来,我读取文件并开始遍历每一行并使用基于 'event' 字段的 switch 语句写入控制台:

foreach (string line in File.ReadAllLines(fileFullPath))
{
  var logHeader = JsonSerializer.Deserialize<LogHeader>(line,options);

  switch (logHeader.Event)
  {
     case "Color":
       var eventColor = JsonSerializer.Deserialize<LogModels.Event.Color>(line, options);
       Console.WriteLine($"The color is {eventColor.Name}.");
       Console.WriteLine($"The Hex value is {eventColor.Hex}.");
     break;
  }

控制台输出为:

The color is Yellow.
The Hex value is #FFFF00.

问题出在嵌套的 JSON 对象上,它们看起来像这样:

{
    "timestamp": "2022-02-09T07:07:52Z",
    "event": "Carpet",
    "Shag": [
        {
            "Color": "Green",
            "Count": 3
        },
        {
            "Color": "Black",
            "Count": 104
        }
    ],
    "Pile": [
        {
            "Color": "Blue",
            "Count": 5
        },
        {
            "Color": "Beige",
            "Count": 13
        }
    ],
    "Outdoor": [
        {
            "Color": "Pebble",
            "Count": 300
        },
        {
            "Color": "Astroturf",
            "Count": 12
        }
    ]
}

在这一点上,我迷路了。我试过创建一个名为“Carpet”的 class,子 classes 名为“Shag”、“Pile”等。我试过为每个 classes 创建单独的 classes亚型。

期望的结果是出现在控制台上:

Shag Carpet -
Green: 3
Black: 104
Pile Carpet -
Blue: 5
Beige: 13
Outdoor Carpet -
Pebble: 300
Astroturf: 12

我无法想象这会像我想象的那么难,但我似乎找不到任何示例来帮助我完成它。

另外,我只在这个网站上发过几次帖,我不确定回复建议等的正确结构

感谢您对此的帮助。

由于您不熟悉编程和 C#,我强烈建议您使用 Newtonsoft.Json 序列化程序。

你可以试试这个代码

Data data = JsonConvert.DeserializeObject<Data>(json);

public class Data
{
    [JsonProperty("timestamp")]
    public DateTime TimeStamp { get; set; }
    [JsonProperty("event")]
    public string Event { get; set; }
    public string Hex { get; set; }
    public string Name { get; set; }
    public List<ColourCount> Shag { get; set; }
    public List<ColourCount> Pile { get; set; }
    public List<ColourCount> Outdoor { get; set; }
}

public class ColourCount
{
    public string Color { get; set; }
    public int Count { get; set; }
}

您可以使用反射进行测试

    var props = data.GetType().GetProperties();

    foreach (var prop in props)
    {
        if (!prop.PropertyType.IsCollectible)
        {
            if(prop.GetValue(data)!=null)
            Console.WriteLine($" {prop.Name} : { prop.GetValue(data).ToString()} ");
        }
        else
        {
            Console.WriteLine($" { prop.Name} - ");

            var items = prop.GetValue(data) as IList<ColourCount>;

            foreach (var item in items)
            {
                Console.WriteLine($" {item.Color} : {item.Count}");
            }
        }
    }

结果

 TimeStamp : 2022-02-09 7:07:52 AM 
 Event : Carpet 
 Shag - 
 Green : 3
 Black : 104
 Pile - 
 Blue : 5
 Beige : 13
 Outdoor - 
 Pebble : 300
 Astroturf : 12

如果您仍想使用 Text.Json 更改 属性 名称属性

Data data = System.Text.Json.JsonSerializer.Deserialize<Data>(json);

public class Data
{
    [JsonPropertyName("timestamp")]
    public DateTime TimeStamp { get; set; }
    [JsonPropertyName("event")]
    public string Event { get; set; }
    .....
}

感谢 Serge 的示例,我是这样做的:

public class Carpet
{
    public List<ColourCount> Shag { get; set; }
    public List<ColourCount> Pile { get; set; }
    public List<ColourCount> Outdoor { get; set; }
}

public class ColourCount
{
    public string Color { get; set; }
    public int Count { get; set; }
}

在 switch 语句中:

  case "Carpet":
     var eventCarpet = JsonSerializer.Deserialize<LogModels.Event.Carpet>(line, options);

     foreach (var shag in eventMaterials.Shag)
     {
        Console.WriteLine($" {shag.Color}: {shag.Count}.");
     }

     foreach (var pile in eventMaterials.Pile)
     {
        Console.WriteLine($" {pile.Color}: {pile.Count}.");
     }

     foreach (var outdoor in eventMaterials.Outdoor)
     {
        Console.WriteLine($" {outdoor.Color}: {outdoor.Count}.");
     }

  break;

这为我提供了所需的控制台输出(减去 'fluff'):

Green : 3
Black : 104
Blue : 5
Beige : 13
Pebble : 300
Astroturf : 12

我知道这可能是您所做的 Fisher-Price 版本,但再次感谢您的帮助!