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>();
}
}
我有以下 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>();
}
}