JSON是这样的:
{
"status": {
"code": 0,
"message": "OK"
},
"data": {
"_idtype": "cusip",
"_id": "00768Y883",
"api": {
"_name": "PortfolioBreakdownsRaw",
"PortfolioDate": "2015-10-12",
"GlobalBondSuperSectorLongSalePositionBreakdown": [
{
"Name": "Municipal",
"Value": "0.57842"
},
{
"Name": "Corporate",
"Value": "1.79649"
},
{
"Name": "Securitized",
"Value": "5.29493"
},
{
"Name": "Cash & Equivalents",
"Value": "166.20776"
}
],
"GlobalBondSuperSectorShortSalePositionBreakdown": [
{
"Name": "Government",
"Value": "0.90557"
}
]
}
}
}
我可以很容易地得到响应的api
部分:
var jObject = JObject.Parse(json);
var api = jObject["data"]["api"];
从这里开始,我不知道是否有任何数组将包含在响应中。最终的目标是创建一个解析器,它将能够获得数组名称(GlobalBondSuperSectorShortSalePositionBreakdown
)和它可能包含的尽可能多的键值对行,而不需要事先知道名称(GlobalBondSuperSectorShortSalePositionBreakdown
)。
我似乎找不到一个好方法来循环对象,确定在api
级别有数组,然后迭代这些数组以获得值。
下面是一个例子。在这段代码中,api
变量保存着一个JObject
,因此我们可以遍历它的属性。从那里,我们查看每个属性值的Type
,看看它是否是一个数组。如果是,那么我们可以遍历该数组以获得其中的JObjects
,并提取我们期望在其中找到的Name
和Value
值。这有帮助吗?
var jObject = JObject.Parse(json);
var api = jObject["data"]["api"];
foreach (JProperty prop in api.Children<JProperty>())
{
JToken value = prop.Value;
if (value.Type == JTokenType.Array)
{
Console.WriteLine(prop.Name + ": ");
foreach (JObject jo in value.Children<JObject>())
{
Console.WriteLine(" " + jo["Name"] + ": " + jo["Value"]);
}
}
else
{
Console.WriteLine(prop.Name + ": " + value);
}
}
输出:_name: PortfolioBreakdownsRaw
PortfolioDate: 2015-10-12
GlobalBondSuperSectorLongSalePositionBreakdown:
Municipal: 0.57842
Corporate: 1.79649
Securitized: 5.29493
Cash & Equivalents: 166.20776
GlobalBondSuperSectorShortSalePositionBreakdown:
Government: 0.90557
小提琴:https://dotnetfiddle.net/XyoXQy
使用Linq可以很好地处理Json.net:
下面是这段代码的一个易于阅读的版本,它将从api元素下的JArray属性中创建两个字典:var api = jObject["data"]["api"];
var arrays = api.Cast<JProperty>().Where(o => o.Value.Type == JTokenType.Array).Select(token => token.Value).ToArray();
var dictionaries = new List<Dictionary<string, string>>();
foreach (var array in arrays)
{
var dictionary = array.ToDictionary(token => token["Name"].Value<string>(), token => token["Value"].Value<string>());
dictionaries.Add(dictionary);
}
选择:
相同的东西,但更短,更紧凑的版本:
var api = jObject["data"]["api"];
var dictionaries = api
.Cast<JProperty>()
.Where(o => o.Value.Type == JTokenType.Array)
.Select(token => token.Value)
.Select(array => array.ToDictionary(token => token["Name"].Value<string>(), token => token["Value"].Value<string>()));