【问题标题】:JSON count only returns 1 instead of 2JSON 计数仅返回 1 而不是 2
【发布时间】:2013-11-22 23:41:19
【问题描述】:

我有这行代码(总是返回 1):

int rowsCount = token["rows"].Count();

token["rows"] 在哪里:

    {
  "component": [
    {
      "tag": "CUT",
      "missingValue": "",
      "format": "Cont",
      "varName": "GPA",
      "label": "Grade point average",
      "element": [
        {
          "startValue": "1",
          "endValue": "249",
          "label": "Lower than 2.50"
        },
        {
          "startValue": "250",
          "endValue": "299",
          "label": "2.50 - 2.99"
        },
        {
          "startValue": "300",
          "endValue": "349",
          "label": "3.00 - 3.49"
        },
        {
          "startValue": "350",
          "endValue": "400",
          "label": "3.50 or higher"
        }
      ]
    },
    {
      "tag": "CAT",
      "missingValue": "",
      "format": "Disc",
      "varName": "STEMMAJ",
      "label": "Major field of study with a focus on STEM fields",
      "element": [
        {
          "value": "1",
          "label": "Math/Computer/Sciences/Engineering/Technologies"
        },
        {
          "value": "2",
          "label": "Social/behavioral sciences"
        },
        {
          "value": "4",
          "label": "Non-STEM field"
        },
        {
          "value": "5",
          "label": "Undecided or not in a degree program"
        }
      ]
    }
  ]
}

我想计算组件的数量。

这也不行:

token["rows"]["component"].Count();

整个 JSON 在这里:

    {
  "version": "1.0",
  "createdBy": "PowerStats v1.0",
  "test": "ohoh",
  "DSNumber": {
    "value": "82"
  },
  "title": {
    "value": ""
  },
  "footnote": {
    "value": ""
  },
  "flagRSE": {
    "value": "30,50",
    "symbol": "!,!!"
  },
  "weight": {
    "type": "0",
    "varName": "WTA000",
    "label": "weight_var"
  },
  "filters": {
    "filter_1": {
      "component": {
        "varName": "JOBEARN2",
        "filterType": "Range",
        "format": "Cont",
        "label": "Job: Earnings from work while enrolled (including work-study)",
        "element": {
          "startValue": "1",
          "endValue": "",
          "label": "X >= 1"
        }
      }
    },
    "filter_2": {
      "component": {
        "varName": "JOBROLE2",
        "filterType": "Dist",
        "format": "Disc",
        "label": "Job: Primary role as student or employee (including work-study)",
        "element": {
          "value": "1",
          "label": "A student working to meet expenses"
        }
      }
    }
  },
  "columns": {
    "component": {
      "tag": "CAT",
      "missingValue": "4,5,6,7,8,9,10,13,14,15,16,17,18,19,20,21,22,23,-3",
      "format": "Disc",
      "varName": "MAJORS23",
      "label": "Field of study: undergraduate (23 categories)",
      "element": [
        {
          "value": "0",
          "label": "Undecided"
        },
        {
          "value": "1",
          "label": "Computer and information sciences"
        },
        {
          "value": "2",
          "label": "Engineering and engineering technology"
        },
        {
          "value": "3",
          "label": "Biological and physical science, science tech"
        },
        {
          "value": "11",
          "label": "Personal and consumer services"
        },
        {
          "value": "12",
          "label": "Manufacturing,construction,repair & transportation"
        }
      ]
    }
  },
  "rows": {
    "component": [
      {
        "tag": "CUT",
        "missingValue": "",
        "format": "Cont",
        "varName": "GPA",
        "label": "Grade point average",
        "element": [
          {
            "startValue": "1",
            "endValue": "249",
            "label": "Lower than 2.50"
          },
          {
            "startValue": "250",
            "endValue": "299",
            "label": "2.50 - 2.99"
          },
          {
            "startValue": "300",
            "endValue": "349",
            "label": "3.00 - 3.49"
          },
          {
            "startValue": "350",
            "endValue": "400",
            "label": "3.50 or higher"
          }
        ]
      },
      {
        "tag": "CAT",
        "missingValue": "",
        "format": "Disc",
        "varName": "STEMMAJ",
        "label": "Major field of study with a focus on STEM fields",
        "element": [
          {
            "value": "1",
            "label": "Math/Computer/Sciences/Engineering/Technologies"
          },
          {
            "value": "2",
            "label": "Social/behavioral sciences"
          },
          {
            "value": "4",
            "label": "Non-STEM field"
          },
          {
            "value": "5",
            "label": "Undecided or not in a degree program"
          }
        ]
      }
    ]
  }
}

【问题讨论】:

  • 你能提供你用来解析 JSON 的代码吗?也许是完整/正确的 JSON 摘录?这样我们就不必重建结构了。
  • 鉴于上述 JSON 作为token["rows"] 的内容,那么Count() 正确返回1。只有一个孩子,component 属性。对于第二部分,您必须解释“这不起作用”的意思。 component 属性的子项计数为 2。
  • 你是怎么数孩子的?
  • .Children().Count() of rows 仍然给我 1

标签: c# .net json json.net


【解决方案1】:

根据您在另一个答案中的 cmets,我现在可以看到您为什么感到困惑。你没有在你的问题中提到你正在做 XML 到 JSON 的转换。

我相信您知道,XML 不像 JSON 那样具有“对象”或“数组”的概念。在 XML 中,一切都只是命名节点的集合。在决定某个东西应该是数组还是对象时,JSON.net 会查看是否有多个同名的同一级别的节点。如果有,那显然是一个数组。但是如果一个节点只有一个孩子,那就是不明确的。它可以是一个包含一项的数组,也可以只是一个简单的对象属性。默认情况下,Json.Net 选择后者。如果您的 XML 中的结果数量可以从零到多个不等,这会使转换为 JSON 时的处理变得更加困难。

为了说明,请考虑以下 XML。在其中,我们有三个不同的“集合”,每个集合中都有不同数量的“项目”。第一个集合只有一个孩子;第二个有两个,最后一个是空的。

<root>
    <collection1>
        <item>
            <label>A</label>
            <value>1</value>
        </item>
    </collection1>
    <collection2>
        <item>
            <label>B</label>
            <value>2</value>
        </item>
        <item>
            <label>C</label>
            <value>3</value>
        </item>
    </collection2>
    <collection3 />
</root>

当使用JsonConvert.SerializeXmlNode() 进行转换时,我们会得到这个 JSON:

{
  "collection1": {
    "item": {
      "label": "A",
      "value": "1"
    }
  },
  "collection2": {
    "item": [
      {
        "label": "B",
        "value": "2"
      },
      {
        "label": "C",
        "value": "3"
      }
    ]
  },
  "collection3": null
}

请注意,在第一个集合中,项目已成为父集合对象的属性,而在第二种情况下,项目被放置在一个数组中,并且该数组已成为 item 属性的值父对象。 (换句话说,实际项目在 JSON 结构中更下一层!)最后一个集合根本没有 item 属性;它的值是null

那么我们该如何处理呢?我们真正需要的是一个辅助方法,它可以处理所有这些不同的情况,并返回我们可以一致使用的项目集合(例如 JArray)。

这是一个应该可以工作的扩展方法:

public static class JsonHelper
{
    public static JArray ToJArray(this JToken token, string itemProperty)
    {
        if (token != null && token.Type != JTokenType.Null)
        {
            token = token[itemProperty];
            if (token != null)
            {
                if (token.Type == JTokenType.Array)
                {
                    return (JArray)token;
                }
                else
                {
                    return new JArray(token);
                }
            }
        }
        return new JArray();
    }
}

这是一个演示,展示了我们如何使用这个辅助方法打印出项目列表:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
          ""collection1"": {
            ""item"": {
              ""label"": ""A"",
              ""value"": ""1""
            }
          },
          ""collection2"": {
            ""item"": [
              {
                ""label"": ""B"",
                ""value"": ""2""
              },
              {
                ""label"": ""C"",
                ""value"": ""3""
              }
            ]
          },
          ""collection3"": null
        }";

        JObject root = JObject.Parse(json);

        DumpItems(root, "collection1");
        DumpItems(root, "collection2");
        DumpItems(root, "collection3");
    }

    private static void DumpItems(JToken token, string collectionName)
    {
        JArray array = token[collectionName].ToJArray("item");

        Console.WriteLine("Count of items in " + collectionName + ": " + array.Count);
        foreach (JToken item in array)
        {
            Console.WriteLine(item["label"] + ": " + item["value"]);
        }
    }
}

输出:

Count of items in collection1: 1
A: 1
Count of items in collection2: 2
B: 2
C: 3
Count of items in collection3: 0

回到你原来的问题,你现在应该可以这样做了:

var count = token["rows"].ToJArray("component").Count;

并获得您期望的价值。

【讨论】:

  • 真的很棒的答案,我希望我可以用 biztalk 或 xslt 开箱即用地做到这一点?
【解决方案2】:

以下代码:

int rowsCount = token["rows"]["component"].Count();

会给你正确的答案。

我用这段代码测试过:

var token = JObject.Parse(...your pasted JSON...);
int rowsCount = token["rows"]["component"].Count();

【讨论】:

  • 但是当只有 1 个组件时会发生什么,那么它会给我列中的元素正确吗?
  • 我不确定我是否理解。如果只有一个组件,则计数将为 1,因为该组件仍应位于具有一个元素的数组 ([]) 中。
  • 要访问第一个元素,您需要执行 token["rows"]["component"][0] 或 token["rows"]["component"].First()
  • 当我使用 JSON.Net 将 XML 转换为 JSON 时,它不会将单个组件放入数组中,如下所示: ..."columns": { "component": { "tag": “猫”,...
  • 如果它在一个数组中,这很容易
【解决方案3】:

您应该在http://jsonlint.com/ 上粘贴可能有帮助的缩进。

问题是因为……嗯,它是一个。 “rows” json 是"rows": {,这意味着......这是一个可怕的名字。这里的行是一个对象(参见{)。它不是一个数组。只有一个。您想要的可能是行内的组件。也许json生成是错误的,但一个是正确的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    相关资源
    最近更新 更多