Json.Net(二)Linq to JSON的操作
Linq to JSON是用来操作JSON对象的,可以用于快速查询、修改和创建JSON对象。
当JSON对象内容比较复杂,而我们仅仅需要其中的一小部分数据时,可以考虑使用Linq to JSON来读取和修改部分的数据而非反序列化全部。
在进行Linq to JSON之前,首先要了解一下用于操作Linq to JSON的类.
类名 | 说明 |
---|---|
<br>JObject<br> |
<br> 用于操作JSON对象<br> |
<br>JArray<br> |
<br> 用语操作JSON数组<br> |
<br>JValue<br> |
<br> 表示数组中的值<br> |
<br>JProperty<br> |
<br> 表示对象中的属性,以"key/value"形式<br> |
<br>JToken<br> |
<br> 用于存放Linq to JSON查询后的结果<br> |
一、创建JObject and JArrary实例
1、手动创建JSON
设置值和一次创建一个对象或数组可以让您完全控制,但是它比其他选项更冗长。
1、创建JSON对象,JObject
JObject staff = new JObject();
staff.Add(new JProperty("Name", "Jack"));
staff.Add(new JProperty("Age", 33));
staff.Add(new JProperty("Department", "Personnel Department"));
staff.Add(new JProperty("Leader", new JObject(new JProperty("Name", "Tom"), new JProperty("Age", 44), new JProperty("Department", "Personnel Department"))));
Console.WriteLine(staff.ToString());
//返回
//{
// "Name": "Jack",
// "Age": 33,
// "Department": "Personnel Department",
// "Leader": {
// "Name": "Tom",
// "Age": 44,
// "Department": "Personnel Department"
// }
//}
2、创建JSON数组,JArrary
JArray arr = new JArray();
arr.Add(new JValue(1));
arr.Add(new JValue(2));
arr.Add(new JValue(3));
Console.WriteLine(arr.ToString());
//返回
//[
// 1,
// 2,
// 3
//]
2、使用Linq创建JSON
使用LINQ声明式地创建JSON对象,是一种从值集合创建JSON的快速方法。
List posts = GetPosts();
JObject rss =
new JObject(
new JProperty("channel",
new JObject(
new JProperty("title", "James Newton-King"),
new JProperty("link", "http://james.newtonking.com"),
new JProperty("description", "James Newton-King's blog."),
new JProperty("item",
new JArray(
from p in posts
orderby p.Title
select new JObject(
new JProperty("title", p.Title),
new JProperty("description", p.Description),
new JProperty("link", p.Link),
new JProperty("category",
new JArray(
from c in p.Categories
select new JValue(c)))))))));
Console.WriteLine(rss.ToString());
//{
// "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 being available on CodePlex",
// "link": "http://james.newtonking.com/projects/json-net.aspx",
// "category": [
// "Json.NET",
// "CodePlex"
// ]
// },
// {
// "title": "LINQ to JSON beta",
// "description": "Announcing LINQ to JSON",
// "link": "http://james.newtonking.com/projects/json-net.aspx",
// "category": [
// "Json.NET",
// "LINQ"
// ]
// }
// ]
// }
//}
3、从对象创建JSON
JObject.FromObject(object o):o为要转化的对象,返回一个JObject对象
最后一个选项是使用FromObject()方法从非JSON类型创建JSON对象。
下面的示例展示了如何从匿名对象创建JSON对象,但是任何. net类型都可以与FromObject一起创建JSON。
var posts = new[] {
new {
Title="Json.NET 1.3 + New license + Now on CodePlex",
Description= "Announcing the release of Json.NET 1.3, the MIT license and being available on CodePlex",
Link="http://james.newtonking.com/projects/json-net.aspx",
Categories=new[]{ "Json.NET","CodePlex"}
},
new {
Title="LINQ to JSON beta",
Description= "Announcing LINQ to JSON",
Link="http://james.newtonking.com/projects/json-net.aspx",
Categories=new[]{ "Json.NET","LINQ"}
},
};
JObject o = JObject.FromObject(new
{
channel = new
{
title = "James Newton-King",
link = "http://james.newtonking.com",
description = "James Newton-King's blog.",
item = //返回数组
from p in posts
orderby p.Title
select new
{
title = p.Title,
description = p.Description,
link = p.Link,
category = p.Categories
}
}
});
Console.WriteLine(o.ToString());
//{
// "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 being available on CodePlex",
// "link": "http://james.newtonking.com/projects/json-net.aspx",
// "category": [
// "Json.NET",
// "CodePlex"
// ]
// },
// {
// "title": "LINQ to JSON beta",
// "description": "Announcing LINQ to JSON",
// "link": "http://james.newtonking.com/projects/json-net.aspx",
// "category": [
// "Json.NET",
// "LINQ"
// ]
// }
// ]
// }
//}
4、解析JSON文本
JObject.Parse(string json):json含有JSON对象的字符串,返回为JObject对象
//解析JSON对象
string json = @"{
CPU: 'Intel',
Drives: [
'DVD read/writer',
'500 gigabyte hard drive'
]
}";
JObject o = JObject.Parse(json);
//解析JSON数组
string json = @"[
'Small',
'Medium',
'Large'
]";
JArray a = JArray.Parse(json);
5、从文件中加载JSON
using (StreamReader reader = File.OpenText(@"c:\person.json"))
{
JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(reader));
// do stuff
}
二、使用JsonConvert.DeserializeObject反序列化JOSN片段
1、数组数据
string jsonArrayText= "[{'a','al'.'b','b1'},{'a','a2'.'b','b2'}]";
JArray ja = (JArray)JsonConvert.DeserializeObject(jsonArrayText); string ja1a==ja[1]["a"].ToString(); //或者 JObject o=(JObject)ja[1]; string ja1a=o["a"].ToString();
2、对象格式
siring jsonText= "{\"beijing\":{\"zone\":\"海淀\",\"zone_en\":\"haidian\"}";
JObject jo =(JObject)JsonConvert.DeserializeObject(jsonArrayText);
string zone =jo["beijing"]["zone"].ToString();
三、修改JObject and JArrary实例
string json = @"{
'post':{
'Title':'修改JArray和JObject',
'Link':'http://write.blog.csdn.net',
'Description':'这是一个修改JArray和JObject的演示案例',
'Item':[]
}
}";
JObject o = JObject.Parse(json);
JObject post = (JObject)o["post"];
post["Title"] = ((string)post["Title"]).ToUpper();
post["Link"] = ((string)post["Link"]).ToUpper();
post.Property("Description").Remove();
post.Property("Link").AddAfterSelf(new JProperty("New", "新添加的属性"));
JArray a = (JArray)post["Item"];
a.Add("修改JArray");
a.Add("修改JObject");
//移除属性
JObject jObj = JObject.Parse(json);
jObj.Remove("Colleagues");//跟的是属性名称
Console.WriteLine(jObj.ToString());
四、查询JObject and JArrary实例
将一个值从LINQ转换为JSON的最简单方法是:使用JObject/JArray上的ItemObject索引,然后将返回的JValue转换为所需的类型。
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
判断Key是否存在
JToken test = new JObject();
if (test["a"] == null)
{
Console.WriteLine("键值key不存在!");
}
JObject test1 = test as JObject;
if (test1.Property("a") == null || test1.Property("a").ToString() == "")
{
Console.WriteLine("键值key不存在!");
}
五、用LINQ表达式进行查询
也可以使用LINQ查询JObject/JArray。
Children()以IEnumerable的形式返回JObject/JArray的子值,然后可以使用标准的Where/OrderBy/Select LINQ操作符查询这些子值。
注意:
Children()返回token的所有子元素。如果它是一个JObject,它将返回一个要使用的属性集合,如果它是一个JArray,您将得到一个数组值的集合。
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
1、可以使用LINQ to JSON手动将JSON转换为. net对象。
当您处理与. net对象不匹配的JSON时,手动序列化和反序列化. net对象是很有用的。
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
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; }
}
六、使用函数SelectToken生成JToken对象可以简化查询语句
1、SelectToken
SelectToken是JToken上的一个方法,它将字符串路径作为子Token名,返回子Token。如果在路径的位置找不到Token,则SelectToken返回空引用。
该路径由属性名和按句点分隔的数组索引组成,例如manufacturer [0]. name。
JObject jObj = JObject.Parse(json);
JToken name = jObj.SelectToken("Name");
Console.WriteLine(name.ToString());
结果:Jack
2、使用LINQ来SelectToken
SelectToken支持JSONPath查询。点击这里了解更多关于JSONPath的信息。
查询最后一名同事的年龄
//将json转换为JObject
JObject jObj = JObject.Parse(json);
var age = jObj.SelectToken("Colleagues[1].Age");
Console.WriteLine(age.ToString());
// 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 pricyProducts = o.SelectTokens("$..Products[?(@.Price >= 50)].Name");
foreach (JToken item in pricyProducts)
{
Console.WriteLine(item);
}
// Anvil
// Elbow Grease
结果:29
3、使用JSONPath来SelectToken
SelectToken可以与标准的LINQ方法结合使用。
利用SelectToken来查询所有同事的名字
JObject jObj = JObject.Parse(json);
var names = jObj.SelectToken("Colleagues").Select(p => p["Name"]).ToList();
foreach (var name in names)
Console.WriteLine(name.ToString());
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"));
结果:Tom Abel
七、如果Json中的Key是变化的但是结构不变,如何获取所要的内容?
例如:
{
"trends": {
"2013-05-31 14:31": [
{
"name": "我不是谁的偶像",
"query": "我不是谁的偶像",
"amount": "65172",
"delta": "1596"
},
{
"name": "世界无烟日",
"query": "世界无烟日",
"amount": "33548",
"delta": "1105"
}
]
},
"as_of": 1369981898
}
其中的"2013-05-31 14:31"是变化的key,如何获取其中的"name","query","amount","delta"等信息呢?
通过Linq可以很简单地做到:
var jObj = JObject.Parse(jsonString);
var tends = from c in jObj.First.First.First.First.Children()
select JsonConvert.DeserializeObject<Trend>(c.ToString());
public class Trend
{
public string Name { get; set; }
public string Query { get; set; }
public string Amount { get; set; }
public string Delta { get; set; }
}
注意:几个First的指向:
八、综合实例
void Main()
{
string json = "{\"Name\" : \"Jack\", \"Age\" : 34, \"Colleagues\" : [{\"Name\" : \"Tom\" , \"Age\":44},{\"Name\" : \"Abel\",\"Age\":29}] }";
// 获取员工名称
JObject jObject = JObject.Parse(json);
var name = jObject.Value<string>("Name");
Console.WriteLine(name);
// 获取员工年龄
JToken jToken = jObject.SelectToken("Age");
Console.WriteLine(jToken.ToString());
// 获取同事信息
JToken jToken1 = jObject["Colleagues"];
Console.WriteLine(jToken1.ToString());
Console.WriteLine("=============================");
// 获取员工同事的所有姓名
var names = from staff in jToken1.Children()
select (string)staff["Name"];
// var names = jObject.SelectToken("Colleagues").Select(p => p["Name"]).ToList();
foreach (var item in names)
{
Console.WriteLine(item);
}
Console.WriteLine("=============================");
// 修改Jack的年龄
jObject["Age"] = 99;
Console.WriteLine(jObject.ToString());
// 修改同事Tome的年龄
jToken1[0]["Age"] = 45;
Console.WriteLine(jObject.ToString());
Console.WriteLine("=============================");
// Abel离职了
jObject["Colleagues"][1].Remove();
Console.WriteLine(jObject.ToString());
// 移除Jack的同事
jObject.Remove("Colleagues");
Console.WriteLine(jObject.ToString());
Console.WriteLine("=============================");
// Jack缺少部门信息
jObject["Age"].Parent.AddAfterSelf(new JProperty("Department", "总裁办"));
// 来了一个新员工Jerry
JObject linda = new JObject(new JProperty("Name", "Linda"), new JProperty("Age", "23"));
jObject.Add(new JProperty("Colleagues", new JArray() { linda }));
Console.WriteLine(jObject.ToString());
}
九、JsonPath表达式
JSONPath表达式总是以与XPath表达式结合使用XML文档的方式引用JSON结构。由于JSON结构通常是匿名的,并且不一定有“根成员对象”,所以JSONPath采用抽象名称 $
分配给外部级别对象。
JSONPath表达式可以使用 点 -符号
$.store.book[0].title
或者 方括号-符号
$['store']['book'][0]['title']
用于输入路径。内部路径或输出路径将始终转换为更通用的括号表示法。。
JSONPath 允许使用通配符 * 作为成员名称和数组索引。 它借用了 E4X 的后代运算符 '..' 和 ECMASCRIPT 4 的数组切片语法建议。[start:end:step]
底层脚本语言的表达式 (<expr>)
可以用作显式名称或索引的替代方法,如(<expr>
)
$.store.book[(@.length-1)].title
对当前对象使用符号“@”。通过语法支持过滤器表达式。如 ?(<boolean expr>)
$.store.book[?(@.price < 10)].title
JSONPath语法元素与其XPath对应项的完整概述和并行比较
XPath | JSONPath | 描述 |
---|---|---|
/ | $ | 根对象/元素 |
. | @ | 当前对象/元素 |
/ | ..或[] | 子操作符 |
.. | N/a | 父操作符 |
// | .. | 递归下降。JSONPath借用了E4X的这个语法。 |
* | * | 通配符。所有对象/元素,无论其名称如何。 |
@ | N/a | 属性访问。JSON结构没有属性。 |
[] | [] | 下标运算符。XPath 使用它来循环访问元素集合和谓词。在 Javascript 和 JSON 中,它是本机数组运算符。 |
[,] | XPath 中的并集运算符生成节点集的组合。JSONPath 允许将备用名称或数组索引作为一个集合。 | |
N/a | [开始:结束:步骤] | 从ES4借用的数组片操作符。 |
[] | ?() | 应用筛选器(脚本)表达式。 |
N/a | () | 脚本表达式,使用底层脚本引擎。 |
() | N/a | XPath中的分组 |
XPath提供的比这里列出的要多得多(非简略语法、运算符和函数中的位置路径)。此外,下标运算符在XPath和JSONPath中的工作方式也有显著差异。
- XPath表达式中的方括号总是在节点集由前面的路径片段产生。指数总是从1开始。
- 使用JSONPath方括号对对象或列阵由前面的路径片段寻址。索引总是从0开始。
下面的例子表示书店的XML示例(原始的XML文件).
void Main()
{
string json = @"{ 'store': {
'book': [
{ 'category': 'reference',
'author': 'Nigel Rees',
'title': 'Sayings of the Century',
'price': 8.95
},
{ 'category': 'fiction',
'author': 'Evelyn Waugh',
'title': 'Sword of Honour',
'price': 12.99
},
{ 'category': 'fiction',
'author': 'Herman Melville',
'title': 'Moby Dick',
'isbn': '0-553-21311-3',
'price': 8.99
},
{ 'category': 'fiction',
'author': 'J. R. R. Tolkien',
'title': 'The Lord of the Rings',
'isbn': '0-395-19395-8',
'price': 22.99
}
],
'bicycle': {
'color': 'red',
'price': 19.95
}
}
}";
//将json转换为JObject
JObject rss = JObject.Parse(json);
var age = rss.SelectTokens("$.store.book[*].author");
foreach (JToken item in age)
{
Console.WriteLine(item);
}
}
XPath | JSONPath | 结果 |
---|---|---|
/store/book/author |
$.store.book[*].author |
商店里所有书的作者 |
//author |
$..author |
所有作者 |
/store/* |
$.store.* |
商店里的所有东西,都是一些书和一辆红色的自行车。 |
/store//price |
$.store..price |
商店里所有东西的价格。 |
//book[3] |
$..book[2] |
第三本书 |
//book[last()] |
$..book[(@.length-1)]``$..book[-1:] |
最后一本书。 |
//book[position()<3] |
$..book[0,1]``$..book[:2] |
前两本书 |
//book[isbn] |
$..book[?(@.isbn)] |
过滤所有ISBN编号的书籍 |
//book[price<10] |
$..book[?(@.price<10)] |
过滤所有低于10的书籍 |
//* |
$..* |
XML文档中的所有元素。JSON结构的所有成员。 |
posted on 2020-02-20 17:09 springsnow 阅读(657) 评论(0) 编辑 收藏 举报