C# json使用之Json.NET(4)——LINQ to JSON

LINQ to JSON是一个用于处理JSON对象的API。 它的设计考虑了LINQ,以便快速查询和创建JSON对象。 LINQ to JSON位于Newtonsoft.Json.Linq命名空间下。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
JObject o = JObject.Parse(@"{
  'CPU': 'Intel',
  'Drives': [
    'DVD read/writer',
    '500 gigabyte hard drive'
  ]
}");
 
string cpu = (string)o["CPU"];
// Intel
 
string firstDrive = (string)o["Drives"][0];
// DVD read/writer
 
IList allDrives = o["Drives"].Select(t => (string)t).ToList();
// DVD read/writer
// 500 gigabyte hard drive

解析JSON

LINQ to JSON具有可用于从字符串解析JSON或直接从文件加载JSON的方法。

Parsing JSON text 解析JSON文本

可以使用Parse(String)从字符串中读取JSON值。

1
2
3
4
5
6
7
8
9
string json = @"{
  CPU: 'Intel',
  Drives: [
    'DVD read/writer',
    '500 gigabyte hard drive'
  ]
}";
 
JObject o = JObject.Parse(json);
1
2
3
4
5
6
7
string json = @"[
  'Small',
  'Medium',
  'Large'
]";
 
JArray a = JArray.Parse(json);

Loading JSON from a file 从文件加载JSON

也可以使用ReadFrom(JsonReader)直接从文件加载JSON。

1
2
3
4
5
using (StreamReader reader = File.OpenText(@"c:\person.json"))
{
    JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(reader));
    // do stuff
}

创建JSON

除了从现有JSON字符串解析JSON之外,还可以从头创建LINQ to JSON对象以创建新的JSON结构。

手动创建json

一次设置一个值并创建一个对象和数组可以完全控制,但它比其他选项更冗长。

1
2
3
4
5
6
7
8
9
10
11
12
JArray array = new JArray();
JValue text = new JValue("Manual text");
JValue date = new JValue(new DateTime(2000, 5, 23));
 
array.Add(text);
array.Add(date);
 
string json = array.ToString();
// [
//   "Manual text",
//   "2000-05-23T00:00:00"
// ]

使用LINQ创建JSON

使用LINQ声明性地创建JSON对象是从值集合创建JSON的快速方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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": "Annoucing 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": "Annoucing LINQ to JSON",
//        "link": "http://james.newtonking.com/projects/json-net.aspx",
//        "category": [
//          "Json.NET",
//          "LINQ"
//        ]
//      }
//    ]
//  }
//}

从对象创建JSON

最后一个选项是使用FromObject()方法从非JSON类型创建JSON对象。 在内部,FromObject将使用JsonSerializer将对象序列化为LINQ to JSON对象而不是文本。

下面的示例显示了从匿名对象创建JSON对象,但任何.NET类型都可以与FromObject一起使用来创建JSON。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
            }
    }
});

使用LINQ查询JSON

LINQ to JSON提供了许多从其对象获取数据的方法。 JObject / JArray上的索引方法允许您通过其属性名称快速获取数据集合中的对象或索引,而Children()允许您获取数据范围作为IEnumerable 然后使用LINQ进行查询。

Getting values by Property Name or Collection Index

从LINQ到JSON获取值的最简单方法是使用JObject / JArray上的Item [Object]索引,然后将返回的JValue转换为所需的类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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': 'Annoucing 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': 'Annoucing 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 categoriesText = categories.Select(c => (string)c).ToList();
// Json.NET
// CodePlex

用LINQ查询

也可以使用LINQ查询JObject / JArray。 Children()将JObject / JArray的子元素值作为IEnumerable 返回,然后可以使用标准的Where / OrderBy / Select LINQ运算符进行查询。

Children()返回令牌的所有子节点。 如果它是一个JObject,它将返回一个要使用的属性集合,如果它是一个JArray,您将获得该数组值的集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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()
    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对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
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对象之间手动序列化和反序列化非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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是JToken上的一个方法,它采用字符串路径到子令牌。 如果在路径的位置找不到令牌,则SelectToken将返回子令牌或空引用。

该路径由以句点分隔的属性名称和数组索引组成,例如:Manufacturers[0].Name

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 with JSONPath

SelectToken支持JSONPath查询。 在此处了解有关JSONPath的更多信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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 pricyProducts = o.SelectTokens("$..Products[?(@.Price >= 50)].Name");
 
foreach (JToken item in pricyProducts)
{
    Console.WriteLine(item);
}
// Anvil
// Elbow Grease

SelectToken with LINQ

SelectToken可与标准LINQ方法结合使用。

1
2
3
4
5
6
7
8
9
10
IList storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList();
// Lambton Quay
// Willis Street
 
IList 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.9

你可能感兴趣的:(C#,json,c#,.net)