【问题标题】:How to loop through nested JSON objects in C#?如何在 C# 中遍历嵌套的 JSON 对象?
【发布时间】:2021-05-03 20:20:25
【问题描述】:

我正在开发一个 C# 项目,我需要调用 API 并解析 JSON 响应。

JSON 响应:

{
    "version": "3.9.1",
     "data": {
        "obj1": {
            "version": "1.0.0",
            "id": "obj1",
            "name": "Object 1",
            "title": "Object 1",
            "info": {
                "info1": 8,
                "info2": 4,
                "info3": 3
            },
            "image": {
                "full": "Object1.png",
                "w": 64,
                "h": 64
            },
            "tags": [
                "Tag1",
                "Tag2"
            ]
        },
        "obj2": {
            "version": "1.0.0",
            "id": "obj2",
            "name": "Object 2",
            "title": "Object 2",
            "info": {
                "info1": 1,
                "info2": 6,
                "info3": 7
            },
            "image": {
                "full": "Object2.png",
                "w": 64,
                "h": 64
            },
            "tags": [
                "Tag1",
                "Tag6"
            ]
        },
        "obj3": {
            "version": "1.0.0",
            "id": "obj3",
            "name": "Object 3",
            "title": "Object 3",
            "info": {
                "info1": 0,
                "info2": 1,
                "info3": 2
            },
            "image": {
                "full": "Object3.png",
                "w": 64,
                "h": 64
            },
            "tags": [
                "Tag7",
                "Tag8"
            ]
        }
    }
}

有了这个响应,我想遍历data 中的所有对象。 data 中的对象数量并不总是相同的。可能只有一个对象或十个对象。

我遇到的问题是我无法循环通过data 属性,因为出现以下错误:

foreach 语句无法对“Objects”类型的变量进行操作,因为“Objects”不包含“GetEnumerator”的公共实例或扩展定义

我知道为什么会出现错误,但我找不到解决问题的方法。

我的代码:

MainWindow.xaml.cs

WebRequest request = WebRequest.Create(path);
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());

string ReaderJson = reader.ReadToEnd();

var JsonResponse = JsonConvert.DeserializeObject<Response>(ReaderJson);

foreach (var obj in JsonResponse.data)
{
    Console.WriteLine(obj.ToString());
}

JsonParser.cs

    public class Response
    {
        public string version { get; set; }
        public Objects data { get; set; }
    }

    public class Objects
    {
        public string id { get; set; }
        public string name { get; set; }
        public string title { get; set; }
        public Info info { get; set; }
        public Images images { get; set; }
    }

    public class Info
    {
        public int info1 { get; set; }
        public int info2 { get; set; }
        public int info3 { get; set; }
    }

    public class Images
    {
        public string full { get; set; }
        public int w { get; set; }
        public int h { get; set; }
    }

如何在不使用obj1obj2 等调用它们的情况下遍历data 中的所有对象?

【问题讨论】:

  • 我猜数据不是你想的那样。看起来数据是一个对象,而不是一个集合。
  • 您的数据模型没有映射到您的 JSON 数据。您的data 属性应该是Dictionary&lt;string, Objects&gt;。 (顺便说一句,类名Objects 在这里有点奇怪;只有集合应该被命名为复数形式。)
  • 啊,好的,谢谢!是的,我想在之后重命名 Objects 类,但我首先想解决这个问题。只是一种糟糕的做法,可悲的是,我经常这样做。
  • 仅供参考:我将该评论正式化为更详细的答案 - 尽管听起来您已经从我的评论中得到了要点。让我知道这是否适合你!

标签: c# json json.net json-deserialization


【解决方案1】:

这里的问题是您的 JSON 架构为 data 定义了一个 字典,但您的 data property 返回一个 >Objects 类的单个实例

数据模型

你想要你的 Response 类看起来像这样:

public class Response
{
    public string version { get; set; }
    public Dictionary<string, Objects> data { get; set; }
}

其他一切都应该没问题。

循环数据

鉴于上述情况,您现在可以使用以下内容循环遍历 data 字典:

foreach (var obj in JsonResponse.data)
{
    Console.WriteLine(obj.Key);
}

注意:当循环通过 Dictionary&lt;TKey, TValue&gt; 时,将返回 KeyValuePair&lt;TKey, TValue&gt;s 的枚举,在 Key 属性中包含您的密钥(即 obj1),以及您的Value 属性中的对象。

命名约定

显然,Objects 这个名字在这里没有意义,因为它代表一个对象,而不是对象的集合。为了与您的代码保持一致,我将其保留为Objects,但您需要给它一个单数名称。我认为这只是您希望它代表一个集合而留下的。

【讨论】:

  • @MrMilkshake:很高兴听到!顺便说一句,如果您控制数据,另一种方法是将 data 视为 JSON 中的一个数组,然后将其映射到 Collection&lt;&gt; — 或者,如果您仍然希望它被键入,那么KeyedCollection&lt;&gt; 基于您的 id 属性。
  • 是的,如果数据确实是一个数组,那会容易得多,但遗憾的是 JSON 作为 API 的响应,我无法更改它 :( 但 KeyedCollection&lt;&gt; 很棒替代我会试一试:D
猜你喜欢
  • 2018-05-13
  • 1970-01-01
  • 2021-07-21
  • 1970-01-01
  • 2019-01-07
  • 1970-01-01
  • 2022-11-21
相关资源
最近更新 更多