.NET Core 3.1中的Json互操作最全解读-收藏级

查找元素(对象

var json = "{"name":"Ron","money":4.5}";
var jDoc = System.Text.Json.JsonDocument.Parse(json);
var obj = jDoc.RootElement[0];// 这里会报错,索引仅支持 Array 类型的 JSON 文档

var jToken = Newtonsoft.Json.Linq.JToken.Parse(json);
var name = jToken["name"];

 

你看,到查找元素环节就体现出差异了,JsonDocuemnt 索引仅支持 Array 类型的 JSON 文档,而 JToken 则支持 object 类型的索引(充满想象),用户体验高下立判。

那我们不禁要提问了,如何在 JsonDocument 中查找元素?答案如下。

var json = "{"name":"Ron","money":4.5}";
var jDoc = System.Text.Json.JsonDocument.Parse(json);
var enumerate = jDoc.RootElement.EnumerateObject();
while (enumerate.MoveNext())
{
if (enumerate.Current.Name == "name")
        Console.WriteLine("{0}:{1}", enumerate.Current.Name, enumerate.Current.Value);
}

 

从上面的代码来看,JsonElement 存在两个迭代器,分别是 EnumerateArray 和 EnumerateObject;通过迭代器,你可以实现查找元素的需求。你看,MS 关上了一扇门,然后又为了打开了一扇窗,还是很人性化的了。在 System.Text.Json 中,一切对象都是 Element,Object/Array/Property,都是 Element,这个概念和 XML 一致,但是和 Newtonsoft.Json 不同,这是需要注意的地方。

你也可以选择不迭代,直接获取对象的属性,比如使用下面的方法

var json = "{"name":"Ron","money":4.5}";
var jDoc = System.Text.Json.JsonDocument.Parse(json);
var age = jDoc.RootElement.GetProperty("age");

 

上面这段代码将抛出异常,因为属性 age 不存在,通常情况下,我们会立即想用一个 ContainsKey 来作一个判断,但是很可惜,JsonElement 并未提供该方法,而是提供了一个 TryGetProperty 方法;所以,除非你明确知道 json 对象中的属性,否则一般情况下,建议使用 TryGetProperty 进行取值。

就算是这样,使用 GetProperty/TryGetProperty 得到的值,还是一个 JsonElement 对象,并不是你期望的“值”。所以 JsonElement 很人性化的提供了各种 GetIntxx/GetString 方法,但是就算如此,还是可能产生意外,思考下面的代码:

var json = "{"name":"Ron","money":4.5,"age":null}";
var jDoc = System.Text.Json.JsonDocument.Parse(json);
var property = jDoc.RootElement.GetProperty("age");
var age = property.GetInt32();

 

上面的代码,最后一行将抛出异常,因为你尝试从一个 null 到 int32 的类型转换,怎么解决这种问题呢,又回到了 JsonElement 上面来,他又提供了一个对值进行检查的方法

if (property.ValueKind == JsonValueKind.Number)
{
var age = property.GetInt32();
}

 

这个时候,程序运行良好,JsonValueKind 枚举提供了一系列的类型标识,为了进一步缩小内存使用率,Json 团队用心良苦的将枚举值声明为:byte 类型(够抠)

public enum JsonValueKind : byte
{
    Undefined = 0,
    Object = 1,
Array = 2,
    String = 3,
    Number = 4,
True = 5,
False = 6,
Null = 7
}

 

看到这里,你是不是有点想念 Newtonsoft.Json 了呢?别着急,下面我给大家介绍一个宝贝 System.Json.dll。

System.Json

 

基本介绍

 

System.Json 提供了对 JSON 对象序列化的基础支持,但是也是有限的支持,请看下图

.NET Core 3.1 中的 Json 互操作最全解读-收藏级

System.Json 目前已合并到 .NETCore-3.1 中,如果你希望使用他,需要单独引用

Install-Package System.Json -Version 4.7.0

 

这个 JSON 互操作包提供了几个常用的操作类型,从下面的操作类不难看出,提供的支持是非常有限的,而且效率上也不好说

System.Json.JsonArray
System.Json.JsonObject
System.Json.JsonPrimitive
System.Json.JsonValue

 

首先,JsonObject 是实现 IDictionary 接口,并在内部维护一个 SortedDictionary<string, JsonValue> 字典,所以他具备字典类的一切操作,比如索引等等,JsonArray 就更简单,也是一样的实现 IList 接口,然后同样的在内部维护一个 List 链表,以实现数组功能,对象的序列化都是通过 JsonValue 进行操作,序列化的方式也是非常的简单,就是对对像进行迭代,唯一值得称道的地方是,采用了流式处理。

使用 System.Json 操作上面的查找过程如下

var obj = System.Json.JsonObject.Parse("{"name":"ron"}");
if (obj.ContainsKey("age"))
{
int age = obj["age"];
}

令人遗憾的是,虽然 System.Json 已经合并到 .NETCore-3.1 的路线图中;但是,System.Text.Json 不提供对 System.Json 的互操作性,我们期待以后 System.Text.Json 也能提供 System.Json 的操作便利性。

© 版权声明

☆ END ☆
喜欢就点个赞吧
点赞0 分享
1 2 3 4
图片正在生成中,请稍后...