json.net 获取所有 json 个令牌并读出特定属性

json.net get all json tokens and readout specific properties

我有以下 json 文件:

{
  "GuiElement0": {
    "gHeight": "50",
    "gID": "0",
    "gY": "80"
  },
  "GuiElement1": {
    "gFile": "",
    "gID": "0",
    "gStyle": "2",
    "gX": "130",
    "gY": "240"
  },
  "GuiElement2": {
    "gThickness": "1",
    "gID": "0",
    "gStyle": "3",
    "gX": "150",
    "gY": "20"
  }
}

现在我想像这样遍历单个元素:

JObject json = JObject.Parse(file.ReadToEnd());
foreach (JToken token in json.Children())
{
    if(JObject.Parse(token.ToString()).GetValue("gID").ToString() == "0" )
    {
        MessageBox.Show(JObject.Parse(token.ToString()).Property("gID").ToString());
    }
}

不幸的是,这没有按预期工作。 我的目标是读出每个标记的 gID,然后分别处理每个元素。

如果我有ID,那么我会反序列化 json

"gThickness": "1",
"gID": "0",
"gStyle": "3",
"gX": "150",
"gY": "20"

像这样:

(GuiElement)JsonConvert.DeserializeObject<GuiBar>(token.ToString());

如果有人能指出我的错误,那就太好了。 谢谢!

我找到了解决方案:

foreach (JProperty prop in json.Children())
{

    JToken value = prop.Value;
    if(value.Type == JTokenType.Object)
    {
        MessageBox.Show(((JObject)value).GetValue("gID").ToString());
    }

}

在您的循环中,token 获取子 json 属性的值。例如,在第一次迭代中它将是 GuiElement0 属性:

"GuiElement0": {
    "gHeight": "50",
    "gID": "0",
    "gY": "80"
}

您不能在这样的 属性 上调用 JObject.Parse(),因为它不是有效的 JSON(它只是其中的一部分)。

无论如何,对同一个 JSON 或其部分进行多次解析不是一个好主意,这样的解决方案性能会很差。相反,只需将迭代的子元素转换为 JProperty 并通过 JProperty.Value:

访问当前元素
foreach (JProperty currProperty in json.Children().OfType<JProperty>())
{
    JToken currElement = currProperty.Value;
    // ...

这里currElement会取GuiElement的值 属性:

{
    "gHeight": "50",
    "gID": "0",
    "gY": "80"
}

您可以通过 JToken.SelectToken() 访问特定的子属性进行比较。我还建议使用强类型 JToken.Value<T> 属性 来提取值:

JToken gIdValue = currElement.SelectToken("gID");
if (gIdValue.Value<int>() == 0)
{
  // ...

最后,您可以使用 JToken.ToObject<T>() 调用反序列化对象 这将避免额外的 JSON 解析。

这是最终代码:

foreach (JProperty currProperty in json.Children().OfType<JProperty>())
{
    JToken currElement = currProperty.Value;
    JToken gIdValue = currElement.SelectToken("gID");
    if (gIdValue.Value<int>() == 0)
    {
        var bar = currElement.ToObject<GuiBar>();
    }
}