Newtonsoft.Json 反序列化
1. Newtonsoft.Json With object
Deserialize an Object
账户类
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
将字符串转化为账户类,并取Email
string json = @"{
'Email': 'james@example.com',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z',
'Roles': [
'User',
'Admin'
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(account.Email);
// james@example.com
Deserialize a Collection
string json = @"['Starcraft','Halo','Legend of Zelda']";
List<string> videogames = JsonConvert.DeserializeObject<List<string>>(json);
Deserialize a Dictionary
string json = @"{
'href': '/account/login.aspx',
'target': '_blank'
}";
Dictionary<string, string> htmlAttributes = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Console.WriteLine(htmlAttributes["href"]);
// /account/login.aspx
Console.WriteLine(htmlAttributes["target"]);
// _blank
Deserialize an Anonymous Type
var definition = new { Name = "" };//定义一个匿名类型
string json1 = @"{'Name':'James'}";
var customer1 = JsonConvert.DeserializeAnonymousType(json1, definition);
Console.WriteLine(customer1.Name);
// James
string json2 = @"{'Name':'Mike'}";
var customer2 = JsonConvert.DeserializeAnonymousType(json2, definition);
Console.WriteLine(customer2.Name);
// Mike
Deserialize a DataSet
string json = @"{
'Table1': [
{
'id': 0,
'item': 'item 0'
},
{
'id': 1,
'item': 'item 1'
}
]
}";
DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(json);
DataTable dataTable = dataSet.Tables["Table1"];
Console.WriteLine(dataTable.Rows.Count);
// 2
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["id"] + " - " + row["item"]);
}
// 0 - item 0
// 1 - item 1
Deserialize with CustomCreationConverter
This sample creates a class that inherits from CustomCreationConverter that instantiates Employee instances for the Person type.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
public class Employee : Person
{
public string Department { get; set; }
public string JobTitle { get; set; }
}
public class PersonConverter : CustomCreationConverter<Person>
{
public override Person Create(Type objectType)
{
return new Employee();
}
}
string json = @"{
'Department': 'Furniture',
'JobTitle': 'Carpenter',
'FirstName': 'John',
'LastName': 'Joinery',
'BirthDate': '1983-02-02T00:00:00'
}";
Person person = JsonConvert.DeserializeObject<Person>(json, new PersonConverter());
Console.WriteLine(person.GetType().Name);
// Employee
Employee employee = (Employee)person;
Console.WriteLine(employee.JobTitle);
// Carpenter
Deserialize JSON from a file
public class Movie
{
public string Name { get; set; }
public int Year { get; set; }
}
Movie movie1 = JsonConvert.DeserializeObject<Movie>(File.ReadAllText(@"c:\movie.json"));
using (StreamReader file = File.OpenText(@"c:\movie.json"))
{
JsonSerializer serializer = new JsonSerializer();
Movie movie2 = (Movie)serializer.Deserialize(file, typeof(Movie));
}
填充对象(Populate an Object)
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public List<string> Roles { get; set; }
}
Account account = new Account
{
Email = "james@example.com",
Active = true,
CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
Roles = new List<string>
{
"User",
"Admin"
}
};
string json = @"{
'Active': false,
'Roles': [
'Expired'
]
}";
JsonConvert.PopulateObject(json, account);
Console.WriteLine(account.Email);
// james@example.com
Console.WriteLine(account.Active);
// false
Console.WriteLine(string.Join(", ", account.Roles.ToArray()));
// User, Admin, Expired
2. Linq to Json 解析JSON
Linq to JSON 具有从字符串解析JSON或直接从文件加载JSON的方法。
- 可以从字符串中读取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);
- 从文件中加载JSON
还可以使用以下方法直接从文件中加载json。ReadFrom(JsonReader).
using (StreamReader reader = File.OpenText(@"c:\person.json"))
{
JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(reader));
// do stuff
}
使用LINQ查询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为可计算,然后可以使用标准WHERE/OrderBy/SelectLINQ运算符对其进行查询。
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对象。
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; }
}
在使用与.NET对象不太匹配的JSON时,.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()提供使用单个字符串路径查询LINQ to JSON的方法, JToken.SelectToken 使动态查询变得容易,因为整个查询都是在字符串中定义的。
SelectToken
SelectToken 是 JToken上的一个方法,它接受一个到child token路径。如果在路径的位置找不到token,SelectToken返回子令牌或空引用。
路径由属性名和数组索引组成,数组索引由句点分隔。 如: 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
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
带有LINQ的SelectToken
** 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
3. JSONPath
使用JSONPath方括号对对象或列阵由前面的路径片段寻址。索引总是从0开始。
JSONPath表达式总是以与XPath表达式结合使用XML文档的方式引用JSON结构。由于JSON结构通常是匿名的,并且不一定有“根成员对象”,所以JSONPath采用抽象名称$分配给外部级别对象。
JSONPath表达式可以使用网点-符号
$.store.book[0].title
或者托架-符号
$[‘store’][‘book’][0][‘title’]
输入路径。内部路径或输出路径将始终转换为更通用的路径。托架-符号。
JSONPath允许通配符成员名称和数组索引的符号*。它借用后人接线员‘.’从…E4X而数组切片语法提案[start🔚step]从…ECMAScript 4.
底层脚本语言的表达式()可以用作显式名称或索引的替代方法,如
$.store.book[(@.length-1)].title
对当前对象使用符号“@”。通过语法支持过滤器表达式。?()如
$.store.book[?(@.price < 10)].title
以下是JSONPath语法元素与其XPath对应项的完整概述和并行比较。
一个简单的JSON结构开始,该结构基于一个表示书店的XML示例(原始的XML文件).
{ "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
}
}
}