我收到这种格式的字符串:
{
"ok": true,
"quote": { // the below is the same as returned through the REST quote API
"symbol": "FAC",
"venue": "OGEX",
"bid": 5100, // best price currently bid for the stock
"ask": 5125, // best price currently offered for the stock
"bidSize": 392, // aggregate size of all orders at the best bid
"askSize": 711, // aggregate size of all orders at the best ask
"bidDepth": 2748, // aggregate size of *all bids*
"askDepth": 2237, // aggregate size of *all asks*
"last": 5125, // price of last trade
"lastSize": 52, // quantity of last trade
"lastTrade": "2015-07-13T05:38:17.33640392Z", // timestamp of last trade,
"quoteTime": "2015-07-13T05:38:17.33640392Z" // server ts of quote generation
}
}
出于性能原因,我想使用Newtonsoft.Json.Linq反序列化方法。当我尝试使用以下方法将Json字符串转换为Quote对象时:
public static Quote QuoteFromJson(string quoteJson)
{
var json = JObject.Parse(quoteJson);
var quote = json["quote"].
Select(q => new Quote
{
Ask = int.Parse(q["ask"].ToString()),
AskDepth = int.Parse(q["askDepth"].ToString()),
AskSize = int.Parse(q["askSize"].ToString()),
Bid = int.Parse(q["bid"].ToString()),
BidDepth = int.Parse(q["bidDepth"].ToString()),
BidSize = int.Parse(q["bidSize"].ToString()),
Last = int.Parse(q["last"].ToString()),
LastSize = int.Parse(q["lastSize"].ToString()),
LastTrade = q["lastTrade"].ToString(),
QuoteTime = q["quoteTime"].ToString(),
Symbol = q["symbol"].ToString(),
}).First();
return quote;
}
这会显示错误消息:
Cannot access child value on Newtonsoft.Json.Linq.JProperty
我做错了什么?
答案 0 :(得分:1)
以下是您问题的直接答案:
quote
变量对应于JSON中的quote
标记。这是一个单独的项目而不是集合,因此您不应将其视为集合并使用Select
方法。
相反,请直接访问它:
var json = JObject.Parse(quoteJson);
var quote = json["quote"];
var result = new Quote
{
Ask = int.Parse(quote["ask"].ToString()),
AskDepth = int.Parse(quote["askDepth"].ToString()),
AskSize = int.Parse(quote["askSize"].ToString()),
Bid = int.Parse(quote["bid"].ToString()),
BidDepth = int.Parse(quote["bidDepth"].ToString()),
BidSize = int.Parse(quote["bidSize"].ToString()),
Last = int.Parse(quote["last"].ToString()),
LastSize = int.Parse(quote["lastSize"].ToString()),
LastTrade = quote["lastTrade"].ToString(),
QuoteTime = quote["quoteTime"].ToString(),
Symbol = quote["symbol"].ToString(),
};
答案 1 :(得分:1)
您的问题是,您正在使用"quote"
对Select
的子项进行迭代,然后按名称检索其属性。如果"quote"
是一个数组,这是合适的,但它不是 - 它已经是一个单独的对象。因此你应该这样做:
var rootObj = JObject.Parse(quoteJson);
var quoteObj = rootObj["quote"];
var quote = new Quote
{
Ask = (int)quoteObj["ask"],
AskDepth = (int)quoteObj["askDepth"],
AskSize = (int)quoteObj["askSize"],
Bid = (int)quoteObj["bid"],
BidDepth = (int)quoteObj["bidDepth"],
BidSize = (int)quoteObj["bidSize"],
Last = (int)quoteObj["last"],
LastSize = (int)quoteObj["lastSize"],
LastTrade = (string)quoteObj["lastTrade"],
QuoteTime = (string)quoteObj["quoteTime"],
Symbol = (string)quoteObj["symbol"],
};
注意我正在使用explicit casting。这以与JSON standard一致的方式处理数字的国际化。 int.Parse()
使用本地化格式进行解析,但不保证与所有语言环境中的标准一致。
但是,使用反序列化要简单得多:
var rootObj = JObject.Parse(quoteJson);
var quoteObj = rootObj["quote"];
var quote = quoteObj.ToObject<Quote>();
我建议你应该花些时间来确保它真的比Linq慢到JSON。