配合LINQ查询JSON
LINQ to JSON提供了很多方法,用来从它的对象中读取数据。JObject/JArray上的索引方法让你能够依靠它在对象上的属性名称或集合中的索引来快速取得数据,而Children()让你能够把数据的范围读取为 IEnumerable<JToken>,然后利用LINQ来查询。
- 通过属性名称或集合索引来取得值
- 利用LINQ查询
通过属性名称或集合索引来取得值
从LINQ to JSON取得值的最简单方法是使用JObject/JArray上的Item[Object]索引,然后把返回的JValue强制转换为你想要的类型。
取得JSON值
string json = @"{
'channel': {
'title': 'James Newton-King',
'link': 'http://james.newtonking.com',
'description': 'James Newton-King\'s blog.',
'item': [
{
'title': 'Json.NET 1.3 + New license + Now on CodePlex',
'description': 'Announcing the release of Json.NET 1.3, the MIT license and the source on CodePlex',
'link': 'http://james.newtonking.com/projects/json-net.aspx',
'categories': [
'Json.NET',
'CodePlex'
]
},
{
'title': 'LINQ to JSON beta',
'description': 'Announcing LINQ to JSON',
'link': 'http://james.newtonking.com/projects/json-net.aspx',
'categories': [
'Json.NET',
'LINQ'
]
}
]
}
}";
JObject rss = JObject.Parse(json);
string rssTitle = (string)rss["channel"]["title"];
// James Newton-King
string itemTitle = (string)rss["channel"]["item"][0]["title"];
// Json.NET 1.3 + New license + Now on CodePlex
JArray categories = (JArray)rss["channel"]["item"][0]["categories"];
// ["Json.NET", "CodePlex"]
IList<string> categoriesText = categories.Select(c => (string)c).ToList();
// Json.NET
// CodePlex
利用LINQ查询
还可以利用LINQ查询JObject/JArray。Children()将JObject/JArray的子元素值返回为一个IEnumerable<JToken>,然后可以利用标准的WHERE/OrderBy/Select LINQ运算符来查询了。
Note |
---|
Children()返回口令的所有子元素。如果它是一个JObject,则将返回一个要处理的属性的集合,如果它是JArray,你将取得数组值的集合。 |
查询JSON
var postTitles =
from p in rss["channel"]["item"]
select (string)p["title"];
foreach (var item in postTitles)
{
Console.WriteLine(item);
}
//LINQ to JSON beta
//Json.NET 1.3 + New license + Now on CodePlex
var categories =
from c in rss["channel"]["item"].SelectMany(i => i["categories"]).Values<string>()
group c by c
into g
orderby g.Count() descending
select new { Category = g.Key, Count = g.Count() };
foreach (var c in categories)
{
Console.WriteLine(c.Category + " - Count: " + c.Count);
}
//Json.NET - Count: 2
//LINQ - Count: 1
//CodePlex - Count: 1
LINQ to JSON还可以用来手工把JSON转换为.NET对象。
利用LINQ对象反序列化
public class Shortie
{
public string Original { get; set; }
public string Shortened { get; set; }
public string Short { get; set; }
public ShortieException Error { get; set; }
}
public class ShortieException
{
public int Code { get; set; }
public string ErrorMessage { get; set; }
}
当你在操作JSON时,如果它并不严密匹配你的.NET对象,则在.NET对象之间手工序列化和反序列化是很有用的。
利用LINQ反序列化的示例
string jsonText = @"{
'short': {
'original': 'http://www.foo.com/',
'short': 'krehqk',
'error': {
'code': 0,
'msg': 'No action taken'
}
}
}";
JObject json = JObject.Parse(jsonText);
Shortie shortie = new Shortie
{
Original = (string)json["short"]["original"],
Short = (string)json["short"]["short"],
Error = new ShortieException
{
Code = (int)json["short"]["error"]["code"],
ErrorMessage = (string)json["short"]["error"]["msg"]
}
};
Console.WriteLine(shortie.Original);
// http://www.foo.com/
Console.WriteLine(shortie.Error.ErrorMessage);
// No action taken
利用SelectToken查询JSON
SelectToken()提供了利用单个字符串路径到想要的JToken来查询LINQ to JSON的方法。SelectToken使动态查询变得很容易,因为整个查询是定义在字符串中的。
- SelectToken
- SelectToken with JSONPath
- SelectToken with LINQ
SelectToken
SelectToken是JToken上的一种方法,取用一个到子口令的字符串路径。SelectToken返回该子口令,或者返回null引用,如果在那个路径的位置没有找到口令的话。
路径是由属性的名称、数组的索引构成,由点号隔开,例如,Manufacturers[0].Name。
SelectToken示例
JObject o = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
],
'Manufacturers': [
{
'Name': 'Acme Co',
'Products': [
{
'Name': 'Anvil',
'Price': 50
}
]
},
{
'Name': 'Contoso',
'Products': [
{
'Name': 'Elbow Grease',
'Price': 99.95
},
{
'Name': 'Headlight Fluid',
'Price': 4
}
]
}
]
}");
string name = (string)o.SelectToken("Manufacturers[0].Name");
// Acme Co
decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price");
// 50
string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name");
// Elbow Grease
SelectToken配合JSONPath
SelectToken支持JSONPath查询。在此处进一步了解JSONPath。
SelectToken配合JSONPath
JObject o = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
],
'Manufacturers': [
{
'Name': 'Acme Co',
'Products': [
{
'Name': 'Anvil',
'Price': 50
}
]
},
{
'Name': 'Contoso',
'Products': [
{
'Name': 'Elbow Grease',
'Price': 99.95
},
{
'Name': 'Headlight Fluid',
'Price': 4
}
]
}
]
}");
// manufacturer with the name 'Acme Co'
JToken acme = o.SelectToken("$.Manufacturers[?(@.Name == 'Acme Co')]");
Console.WriteLine(acme);
// { "Name": "Acme Co", Products: [{ "Name": "Anvil", "Price": 50 }] }
// name of all products priced 50 and above
IEnumerable<JToken> pricyProducts = o.SelectTokens("$..Products[?(@.Price >= 50)].Name");
foreach (JToken item in pricyProducts)
{
Console.WriteLine(item);
}
// Anvil
// Elbow Grease
SelectToken配合LINQ
SelectToken可以与标准LINQ方法结合使用。
SelectToken配合LINQ的示例
IList<string> storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList();
// Lambton Quay
// Willis Street
IList<string> firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList();
// null
// Headlight Fluid
decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price"));
// 149.95