这是我正在使用的JSON字符串。
string jsonText = "{
"?xml" : {
"@version" : "1.0",
"@encoding" : "UTF-8",
"@standalone" : "yes"
},
"Grid" : {
"DataRow" : [{
"DataItem" : [{
"@name" : "SYMBOL",
"#text" : "005930"
}, {
"@name" : "NAME",
"#text" : "Samsung Electronics"
}, {
"@name" : "PRICE",
"#text" : "1004.3"
}, {
"@name" : "VOLUME",
"#text" : "273.182"
}, {
"@name" : "AGG_VOLUME",
"#text" : "302.894"
}
]
}, {
"DataItem" : [{
"@name" : "SYMBOL",
"#text" : "AAPL"
}, {
"@name" : "NAME",
"#text" : "Apple Inc."
}, {
"@name" : "PRICE",
"#text" : "99"
}, {
"@name" : "VOLUME",
"#text" : "32936.4"
}, {
"@name" : "AGG_VOLUME",
"#text" : "33078.769"
}
]
}, {
"DataItem" : [{
"@name" : "SYMBOL",
"#text" : "MSFT"
}, {
"@name" : "NAME",
"#text" : "Microsoft Corporation"
}, {
"@name" : "PRICE",
"#text" : "42"
}, {
"@name" : "VOLUME",
"#text" : "103441.6"
}, {
"@name" : "AGG_VOLUME",
"#text" : "1324432.074"
}
]
}
]
}
}"
JObject feed = JObject.Parse(jsonText);
我正在尝试获取SYMBOL、NAME、PRICE和&AGG_VOLUME。到目前为止,这是我的代码:
var covg = feed["DataItem"]["@name"].Select(f => (string)f.SelectToken("#text"));
但我得到了以下错误:
对象引用未设置为对象的实例。
我做错了什么?
JToken.SelectTokens()
支持JSONPath查询语法。您可以使用此语法来执行所需的查询:
-
".."
是通配符递归下降运算符。因此,feed.SelectTokens("..DataItem")
查找所有名为DataItem
的JSON属性的值,无论它们在JSON层次结构中的位置如何。 -
"[?(@.@name == 'Value')]"
查询具有名为@name
、值为Value
的属性的数组中的对象。
因此,以下内容可以满足您的需要:
var feed = JObject.Parse(jsonText);
var query = from item in feed.SelectTokens("..DataItem")
select new
{
SYMBOL = (string)item.SelectToken("[?(@.@name == 'SYMBOL')].#text"),
NAME = (string)item.SelectToken("[?(@.@name == 'NAME')].#text"),
PRICE = (string)item.SelectToken("[?(@.@name == 'PRICE')].#text"),
AGG_VOLUME = (string)item.SelectToken("[?(@.@name == 'AGG_VOLUME')].#text")
};
var list = query.ToList();
您得到此错误是因为feed
引用的根JObject
不直接包含DataItem
属性。因此CCD_ 11返回null。当您尝试取消引用这个null表达式时,它会抛出一个NullReferenceException
。
您试图获取的数据在JSON中有好几层,因此您的查询必须考虑到这一点。例如,要获得JSON中所有SYMBOL
值的列表,您需要执行以下操作:
List<string> symbols =
feed.SelectToken("Grid.DataRow")
.SelectMany(jt => jt["DataItem"])
.Where(jt => (string)jt["@name"] == "SYMBOL")
.Select(jt => (string)jt["#text"])
.ToList();
Fiddle:https://dotnetfiddle.net/jxZGZC