LINQ to JSON - ошибка SelectToken
Это строка 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"));
Но я получаю следующую ошибку:
В экземпляре объекта не задана ссылка на объект.
Что я делаю неправильно?
2 ответа
JToken.SelectTokens()
поддерживает синтаксис запросов JSONPath. Вы можете использовать этот синтаксис для выполнения запроса, который вам требуется:
".."
является подстановочным оператором рекурсивного спуска таким образомfeed.SelectTokens("..DataItem")
находит значения всех именованных свойств JSONDataItem
независимо от того, где они находятся в иерархии 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
имущество. таким образом feed["DataItem"]
возвращает ноль. Когда вы затем пытаетесь разыменовать это нулевое выражение, оно выдает NullReferenceException
,
Данные, которые вы пытаетесь получить, находятся в нескольких слоях в JSON, поэтому ваш запрос должен это учитывать. Чтобы получить список всех SYMBOL
например, значения в JSON, вам нужно сделать что-то вроде этого:
List<string> symbols =
feed.SelectToken("Grid.DataRow")
.SelectMany(jt => jt["DataItem"])
.Where(jt => (string)jt["@name"] == "SYMBOL")
.Select(jt => (string)jt["#text"])
.ToList();
Скрипка: https://dotnetfiddle.net/jxZGZC