将 JSON 反序列化为自定义列表 [英] Deserialize JSON into custom list
问题描述
我有这个 json:
var x = [
[99,"abc","2dp",{"GroupNum": 0,"Total":[4, 1]}],
[7,"x","date"],
[60,"x","1dp",{"GroupNum": 1}],
...
]
存在以下规则(让 i
指代内部列表索引):
The following rules exist (let i
refer to the inner list index):
x[i][0]
- 必填项 - 始终为整数x[i][1]
- 必填项 - 总是一个字符串x[i][2]
- 必填项 - 总是一个字符串x[i][3]
- 可选项目 - 当它存在时,它具有以下规则:x[i][3].GroupNum
- 必填字段 - 始终为整数x[i][3].Total
- 可选字段 - 当它存在时,它是一个整数列表
x[i][0]
- mandatory item - always an integerx[i][1]
- mandatory item - always a stringx[i][2]
- mandatory item - always a stringx[i][3]
- optional item - when it exists then it has the following rules:x[i][3].GroupNum
- mandatory field - always an integerx[i][3].Total
- optional field - when it exists then it is a list of integers
所以我为这些规则创建了以下类:
So I have created the following classes for these rules:
public class ReportTemplateField : System.Collections.CollectionBase { public object this[int index] { get { switch (index) { case 0: return (int)List[index]; case 1: case 2: return (string)List[index]; case 3: return (ReportGrouping)List[index]; default: throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items"); } } set { switch (Count) { case 0: List[index] = unchecked((int)value); break; case 1: case 2: List[index] = (string)value; break; case 3: List[index] = (ReportGrouping)value; break; default: throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items"); } } } public void Add(object item) { switch (Count) { case 0: List.Add(unchecked((int)item)); break; case 1: case 2: List.Add((string)item); break; case 3: List.Add((ReportGrouping)item); break; default: throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items"); } } } public class ReportGrouping { public int GroupNum { get; set; } public List<int> Total { get; set; } }
然而,当我尝试使用 json.net 反序列化时,
ReportTemplateField
类永远不会被使用.我知道这一点是因为我在每个方法中都设置了断点,但没有一个被触发:However, when I attempt to deserialize using json.net, the
ReportTemplateField
class never gets used. I know this because I have put breakpoints in every method and none of them get triggered:string json = "[[99,"abc","2dp",{"GroupNum": 0,"Total":[4, 1]}],[7,"x","date"],[60,"x","1dp",{"GroupNum": 1}]]"; List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json); int Total01 = parsed[0][3].Total[1];
给我这个错误:
错误 CS1061:对象"不包含总计"的定义和没有接受第一个类型参数的扩展方法Total"可以找到对象"(您是否缺少 using 指令或汇编参考?)
error CS1061: 'object' does not contain a definition for 'Total' and no extension method 'Total' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
但是,如果我只是单独反序列化
ReportGrouping
,它会起作用:However it works if I just deserialize the
ReportGrouping
in isolation:string json2 = "{"GroupNum": 0,"Total":[4, 1]}"; ReportGrouping parsed2 = JsonConvert.DeserializeObject<ReportGrouping>(json2); parsed2.Total[1]; // 1
所以问题在于
ReportTemplateField
类.也许我不应该从System.Collections.CollectionBase
继承?我基本上按照此演练进行了一些修改 - https://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx 但它确实说文档可能已经过时.我使用的是 .NET 4.5,所以请将其纳入您的任何答案中.So the problem lies with the
ReportTemplateField
class. Maybe I shouldn't be inheriting fromSystem.Collections.CollectionBase
? I basically followed this walkthough with some modifications - https://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx but it does say that the documentation may be outdated. I'm using .NET 4.5 so please factor that into any your answers.我怎样才能让 Json.net 正确反序列化,这样我就可以去
parsed[0][3].Total[1];
访问第二个总数的整数值,而不需要需要投射它或对它做任何事情吗?How can I get Json.net to deserialize correctly, so that I can just go
parsed[0][3].Total[1];
to access the integer value of the second total without needing to cast it or do anything to it at all?推荐答案
代码中有几个错误,一是对象没有名为 Total 的属性,二是 parsed[0][3] 是一个字符串.
There is a few errors in the code, 1 is that object does not have a property called Total and another is that parsed[0][3] is a string.
您的代码中有一些错误:
You have a few errors in the code:
- parsed[0][3] 是一个字符串.通过将字符串转换为 ReportGrouping 来修复它.
- new ReportGrouping().GroupName 应根据 Json 命名为 Group.
在您将 parsed[0][3] 解析为 ReportingGroup 后,它仍会返回一个对象,因此之后将 i 转换为 ReportingGroup.IE.(ReportingGroup)parsed[0][3].
- parsed[0][3] is a string. Fix it by converting the string into a ReportGrouping.
- new ReportGrouping().GroupName should be named Group according to Json.
After you have parsed parsed[0][3] into a ReportingGroup it will still return a object, so cast i into a ReportingGroup afterwards. I.e. (ReportingGroup)parsed[0][3].
get { switch (index) { case 0: return (int)List[index]; case 1: case 2: return (string)List[index]; case 3: return JsonConvert.DeserializeObject<ReportGrouping>(List[index].ToString()); default: throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items"); } }
并像这样使用它:
List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json); ReportGrouping group = (ReportGrouping)parsed[0][3];
不要忘记将 GroupName 重命名为 Group 并修复 setter.
Dont forget to rename GroupName into Group and to fix the setter.
抱歉我重复了这么多次..
Sorry for repeating myself so many times..
这篇关于将 JSON 反序列化为自定义列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!