使用Json.NET,如何将具有动态名称的对象列表解析为List?

时间:2016-11-19 21:42:52

标签: c# json web json.net

以下是我从外部API接收的JSON格式示例:

const int table[] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432};
const char *a_z = "abcdefghijklmnopqrstuvwxyz";
long long int sum[2] = {0};
int ch, count = 0;

for(;;)
{
    if(!islower(ch = getchar()))
    {
        if(ch == '\n' && sum[0] && sum[1])
            break;
        else if(ch == EOF)
            {
            printf("Wrong.\n");
            }
        else if(ch == '|' && sum[0] != 0 && count == 0)
            {
            count = 1;
            continue;
            }
    printf("Wrong.\n");
    sum[0] = sum[1] = count = 0;
    while(ch != '\n' && (ch=getchar())!=EOF && ch != '\n')
    continue;
    }
sum[count] += table[strchr(a_z, ch) - a_z];
}

有大约100种不同的属性类型可以发送,但它们都遵循相同的结构。唯一的区别是属性的名称(“property_1”,“property_5”等)。我没有尝试使用一长串不常用的属性来编写一个类,而是认为将它解析为对象列表会更有用,在结果类中使用属​​性名称,如下所示:

"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"
    }
  }
}

在这种情况下,属性名称(“property_1”,“property_5”等)将分配给Property对象的Name字段。

如何使用Json.NET实现这一目标?

2 个答案:

答案 0 :(得分:10)

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; }
}
BTW:Json.Net比@MatíasFidemraizer提议的更容易处理动态 ...

var val = ((dynamic)JsonConvert.DeserializeObject(jsonstring))
          .@object.property_14.values.value;

var val = ((dynamic)JsonConvert.DeserializeObject(jsonstring))
          .@object["property_14"].values.value;

但是这种方法要求您事先知道服务器将返回property_14 ...

答案 1 :(得分:2)

还有另一种方法:您可以使用expando objects

dynamic response = JsonConvert.DeserializeObject<ExpandoObject>("JSON TEXT", new ExpandoObjectConverter());

您可以使用动态类型访问属性:

long someValue = response.@object.property_1.values.value;

此外,由于ExpandoObject实现IDictionary<string, object>,您可以像字典一样使用它并检查属性是否存在:

if(((IDictionary<string, object>)response.@object).ContainsKey("property_1"))
{

}

看起来你可以节省很多时间!

回答这个答案的仇恨

似乎对我的回答最讨厌的是@EZI的评论:

  

假设你在反序列化json之前不知道property_14 ..

另一位回答者@ L.B在他自己的回答中辩称:

  

但是这种方法需要你知道property_14会是什么   事先由您的服务器返回...

就我而言,当我提到ExpandoObject实施IDictionary<string, object>时,我发现我的回答已经解决了这个问题。也许您不知道property_14将成为反序列化对象图的一部分。 没问题

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;
}