无法在 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 版本,但再次感谢您的帮助!
我是编程和 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':
的基础 classnamespace 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 版本,但再次感谢您的帮助!