C# 使用Json.NET,如何将具有动态名称的对象列表解析为列表?
下面是我从外部API接收的JSON格式示例:C# 使用Json.NET,如何将具有动态名称的对象列表解析为列表?,c#,json,web,json.net,C#,Json,Web,Json.net,下面是我从外部API接收的JSON格式示例: "object": { "property_1": { "values": { "value": 1, "displayValue": "1" } }, "property_5": { "values": { "value": 3, "displayValue": "3" } }, "property_8": { "values": {
"object": {
"property_1": {
"values": {
"value": 1,
"displayValue": "1"
}
},
"property_5": {
"values": {
"value": 3,
"displayValue": "3"
}
},
"property_8": {
"values": {
"value": 1,
"displayValue": "1"
}
},
"property_14": {
"values": {
"value": 392,
"displayValue": "392.0"
}
},
"property_17": {
"values": {
"value": 14,
"displayValue": "14"
}
}
}
大约有100种不同的属性类型可以发送,但它们都遵循相同的结构。唯一的区别是财产的名称(“财产1”、“财产5”等)。与其尝试编写一个包含一长串不经常使用的属性的类,不如将其解析为一个对象列表,在生成的类中使用属性名,如下所示:
public class Property
{
public string Name { get; set; }
public PropertyValues Values { get; set; }
}
public class PropertyValues
{
public double Value { get; set; }
public string DisplayValue { get; set; }
}
在这种情况下,属性名称(“属性_1”、“属性_5”等)将分配给属性对象的名称字段
如何使用Json.NET实现这一点?还有另一种方法:您可以使用: 此外,由于
ExpandoObject
实现了IDictionary
,因此您可以像使用字典一样使用它,并检查属性是否存在:
if(((IDictionary<string, object>)response.@object).ContainsKey("property_1"))
{
}
但这种方法需要您知道服务器将提前返回
property_14
。非常通用,可以发布到任何与json相关的问题上。。。。假设在反序列化json之前,您不知道property_14
,它甚至不起作用<代码>字符串property14Value=response.property14Value抛出异常…@EZI很抱歉,但您知道它为什么抛出异常,因为它应该是response.object.property14value
。我要解决这个问题。@EZI解决了,顺便说一句,我觉得我得到了很多爱和恨(3次反对票),而这种方法在很多场景中都能完美地工作。而且,我希望OP能利用我的方法。我给了一个错误的动态属性访问权限,这只是一个人为错误,虽然这并没有违背我回答的目的:我给OP一个很好的提示。顺便说一句:我也想知道在测试这个答案中的代码之前/之后,谁投了+1或-1的票……如果说其他贡献者重复了你的答案,而整个答案的一部分正是我提供的方法,那就太可怕了。在其他问答中,由于其他回答者比你更成熟,通常会使用指向其他回答者的链接,说“就像在他的回答中已经说过@matias fidemraizer一样,你也可以使用动态方法”。。。事实上,我关心的是提供我认为对OP有用的好答案和建议。就我而言,我不是一个追名逐利的人,我只是回答我的观点,我不关心你是否获得100多张赞成票,甚至是反对票。嗯,我关心的是我是否获得反对票来改进我的答案。谢谢你的提醒。根据我的经验,在这种情况下,最好使用ExpandoObject
而不是JObject
,因为请记住,JSON.NET提供了隐式转换,将JSON值转换为简单类型,如string
、bool
、int
,这可能会导致一些重载解决问题。。。顺便说一句,在其他情况下,将动态
反序列化为作业对象
就足够了……现在,当您再次编辑时,我理解了您和@EZI的顾虑,并展示了如何访问“property_14”
。我发现当您使用ExpandoObject
时,这些问题就消失了。现在OP有2到3种方法来解决相同的问题。现在我要睡觉了!晚安
long someValue = response.@object.property_1.values.value;
if(((IDictionary<string, object>)response.@object).ContainsKey("property_1"))
{
}
if(((IDictionary<string, object>)response.@object).ContainsKey("property_14"))
{
// You've already addressed the issue, because you won't get a
// run-time exception since you'll access such property if it's already
// in the returned response...
object property_14 = response.@object.property_14;
}
var result = JsonConvert.DeserializeObject<Root>(json);
public class Root
{
public Dictionary<string, ValueWrapper> Object { get; set; }
}
public class ValueWrapper
{
public PropertyValues Values { get; set; }
}
public class PropertyValues
{
public int Value { get; set; }
public string DisplayValue { get; set; }
}
var val = ((dynamic)JsonConvert.DeserializeObject(jsonstring))
.@object.property_14.values.value;
var val = ((dynamic)JsonConvert.DeserializeObject(jsonstring))
.@object["property_14"].values.value;