将嵌套的 JSON 反序列化为 C# 对象
Posted
技术标签:
【中文标题】将嵌套的 JSON 反序列化为 C# 对象【英文标题】:Deserialize nested JSON into C# objects 【发布时间】:2016-12-12 02:24:38 【问题描述】:我从如下所示的 API 获取 JSON:
"Items":
"Item322A": [
"prop1": "string",
"prop2": "string",
"prop3": 1,
"prop4": false
,
"prop1": "string",
"prop2": "string",
"prop3": 0,
"prop4": false
],
"Item2B": [
"prop1": "string",
"prop2": "string",
"prop3": 14,
"prop4": true
]
,
"Errors": ["String"]
我已经尝试了几种方法来在 c# 对象中表示这个 JSON(这里列出的太多了)。我尝试过使用列表和字典,这是我最近尝试表示的示例:
private class Response
public Item Items get; set;
public string[] Errors get; set;
private class Item
public List<SubItem> SubItems get; set;
private class SubItem
public List<Info> Infos get; set;
private class Info
public string Prop1 get; set;
public string Prop2 get; set;
public int Prop3 get; set;
public bool Prop4 get; set;
这是我用来反序列化 JSON 的方法:
using (var sr = new StringReader(responseJSON))
using (var jr = new JsonTextReader(sr))
var serial = new JsonSerializer();
serial.Formatting = Formatting.Indented;
var obj = serial.Deserialize<Response>(jr);
obj
包含 Items
和 Errors
。而Items
包含SubItems
,但SubItems
是null
。因此,除了Errors
之外,实际上没有任何东西被反序列化。
应该很简单,但由于某种原因我无法找出正确的对象表示
【问题讨论】:
【参考方案1】:使用此站点进行表示:
https://quicktype.io/csharp/
这样的事情可能会对你有所帮助
public class Item322A
public string prop1 get; set;
public string prop2 get; set;
public int prop3 get; set;
public bool prop4 get; set;
public class Item2B
public string prop1 get; set;
public string prop2 get; set;
public int prop3 get; set;
public bool prop4 get; set;
public class Items
public List<Item322A> Item322A get; set;
public List<Item2B> Item2B get; set;
public class jsonObject
public Items Items get; set;
public List<string> Errors get; set;
这里是如何反序列化(使用 JsonConvert 类):
jsonObject ourlisting = JsonConvert.DeserializeObject<jsonObject>(strJSON);
【讨论】:
Item322A 和 Item2B 不是常量。不过谢谢你的回答 作为对此感兴趣的任何人的后续行动。如果您使用 Visual Studio,则可以使用“选择性粘贴”功能。并且基本上与此答案中的链接站点相同。也适用于 XML【参考方案2】:对于"Items"
,使用Dictionary<string, List<Info>>
,即:
class Response
public Dictionary<string, List<Info>> Items get; set;
public string[] Errors get; set;
class Info
public string Prop1 get; set;
public string Prop2 get; set;
public int Prop3 get; set;
public bool Prop4 get; set;
这假定项目名称 "Item322A"
和 "Item2B"
会因响应而异,并将这些名称作为字典键读取。
示例fiddle。
【讨论】:
酷,我要试试这个。我只是尝试了一种类似的方法,但是将字典包含在一个列表中! 这行得通。原来我的最后一次尝试是如此接近【参考方案3】:您可以使用Json.Parse
来查询数据——并且只使用单个模型。
private class Info
public string Prop1 get; set;
public string Prop2 get; set;
public int Prop3 get; set;
public bool Prop4 get; set;
var result = JObject.Parse(resultContent); //parses entire stream into JObject, from which you can use to query the bits you need.
var items = result["Items"].Children().ToList(); //Get the sections you need and save as enumerable (will be in the form of JTokens)
List<Info> infoList = new List<Info>(); //init new list to store the objects.
//iterate through the list and match to an object. If Property names don't match -- you could also map the properties individually. Also useful if you need to dig out nested properties.
foreach(var subItem in items)
foreach(JToken result in subItem)
Info info = result.ToObject<Info>();
infoList.add(info);
【讨论】:
以上是关于将嵌套的 JSON 反序列化为 C# 对象的主要内容,如果未能解决你的问题,请参考以下文章
如何将具有嵌套属性的 JSON 对象反序列化为 Symfony 实体?