【问题标题】:Parsing JSON in C# without object names在没有对象名称的 C# 中解析 JSON
【发布时间】:2017-11-04 21:40:09
【问题描述】:

我对 C# 有点陌生,在解析一些嵌套的 JSON 对象时遇到了一些麻烦。

我正在发出一个返回一些 JSON 的 GET 请求。我已经尽可能地简化了它,使它容易过一遍。 JSON 响应的一个示例是:

{
"response": {
"ITEM1": {
  "RANDOM_DATE": {
    "mean": 150,
    "min": 150,
    "max": 150
  }
},
"ITEM2": {
  "RANDOM_DATE2": {
    "mean": 200,
    "min": 200,
    "max": 200
  },
  "RANDOM_DATE3": {
    "mean": 150,
    "min": 150,
    "max": 150
  }
}
}
}

我目前拥有的是:

dynamic response = JObject.Parse(await client.DownloadStringTaskAsync(url));
foreach (dynamic item in response["response"])           
{ 
    string name = item.ToString();
    string valueInCentsStr = "0";
    int valueInCents = 0;

    foreach (dynamic day in response["response"][item])
    {
        valueString = response["response"][item][day].min;
        valueInt = int.Parse(valueString);
    }
}

所以现在 item.ToString() 完全没问题。该函数正常运行并返回 ITEM1 和 ITEM2。

问题是,嵌套的对象名称总是不同的,这就是为什么我添加了一个嵌套的 foreach 来遍历每个 ITEM 以获取每天的数据。但是,这似乎不起作用。我得到一个错误指向那个 foreach 说:

System.AggregateException: One or more errors occurred. ---> System.ArgumentException: Accessed JObject values with invalid key value:

我更习惯于 JavaScript,这在 JS 中运行良好。你将如何改变它以便能够从嵌套对象中获取信息?

谢谢。

【问题讨论】:

  • 您需要将元素名称传递给响应索引器(就像您使用 `response["response"] 所做的那样),但您传递的是元素本身。除非绝对必要,否则最好避免使用动态和使用编译时类型检查的好处(这里不是)。
  • 哦,没看到这个回复,我回去改一下我的其他代码。不知道为什么我要让一切都充满活力。谢谢!

标签: c# json json.net


【解决方案1】:

由于您已经在使用 Json.NET,反序列化 JSON 的最简单方法是定义以下类型:

public class RootObject
{
    public Dictionary<string, Dictionary<string, DateValue>> response { get; set; }
}

public class DateValue
{
    public int mean { get; set; }
    public int min { get; set; }
    public int max { get; set; }
}

(您可能需要将meanminmax 更改为decimaldouble 类型,如果在您的实际JSON 中,这些值可以是小数。)

然后反序列化如下:

var root = JsonConvert.DeserializeObject<RootObject>(response);

相关文档:Deserialize a Dictionary.

示例fiddle

请注意,如果您的 "RANDOM_DATE" 字符串实际上是 Json.NET 可识别的 DateTime 格式(有关此类格式的列表,请参阅 here),您可以按如下方式定义您的 RootObject

public class RootObject
{
    public Dictionary<string, Dictionary<DateTime, DateValue>> response { get; set; }
}

【讨论】:

  • 感谢您的回复。是的,它们确实是实际日期,但我只需要其中的信息,而不是日期本身。不过谢谢:)另外,你会推荐更多。您的解决方案还是 Tadija 的解决方案?我通常会用他的解决方案来做,但我已经看到很多像你这样的 C# 代码。
  • 在@Evk 的评论中,我的回答为您提供了静态类型的优势,这有助于防止错误并确保代码在编译后能够正常工作。该站点还声称反序列化为固定类型的性能稍好:stackify.com/top-11-json-performance-usage-tips。但是,正如tour stackoverflow 中所解释的,答案主要是关于如何 做事而不是哪种解决方案最好
  • 知道了,谢谢,我只是好奇我将来应该做什么。感谢您的帮助:)
  • 反序列化到类而不是动态化绝对是更多的规范和一个好的起点。如果成本太高,您可以随时进行优化
猜你喜欢
  • 2023-03-25
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 2023-02-03
  • 1970-01-01
  • 2019-10-26
  • 2020-08-09
相关资源
最近更新 更多