另一篇使用 System.Text.Json 序列化和反序列化Json使用的是反序列化的方式来读取JSON文件,不过那种方式依赖于类。
除此之外,System.Text.Json还提供了JsonDocument,JsonNode和Utf8JsonReader三种方式来读取JSON,而且这三种可以不依赖于具体的类型。
比如以下JSON文件,就可以通过这三种不同的方式来读取想要的值。
{
"organization": "vdeveloper.net",
"address":{
"city":"GuangZhou",
"province":"GuangDong",
"zipCode":"510000"
},
"staffs":[{
"firstName":"Zhang",
"lastName":"San"
},{
"firstName":"Li",
"lastName":"Si"
}]
}
JsonDocument
var jdoc = JsonDocument.Parse(str);
Console.WriteLine($"organization:{jdoc.RootElement.GetProperty("organization").GetString()}");
var addressEle = jdoc.RootElement.GetProperty("address");
Console.WriteLine($"City:{addressEle.GetProperty("city").GetString()}");
var staffsEle = jdoc.RootElement.GetProperty("staffs").EnumerateArray();
foreach(var staffEle in staffsEle)
{
Console.WriteLine($"{staffEle.GetProperty("firstName").GetString()} {staffEle.GetProperty("lastName").GetString()}");
}
- 静态方法 JsonDocument.Parse 把JSON字符串或者流转换成 JsonDocument 对象
- RootElement 是 JsonDocument 的根节点
- GetProperty 返回 JsonElment 对象,该对象包含一系列取值的方法,例如 GetString()
- 除了 GetString(), JsonElment 还有 Deserialize 方法,可以将该节点反序列化成指定的对象。
- EnumerateArray 也是JsonElment的方法,适用于数组的循环
JsonNode
var jnode = JsonNode.Parse(str);
Console.WriteLine($"organization:{jnode!["organization"]!.GetValue<string>()}");
var addressNode = jnode!["address"];
Console.WriteLine($"City:{addressNode!["city"]!.GetValue<string>()}");
Console.WriteLine($"Province:{jnode!["address"]!["province"]!.GetValue<string>()}");
var staffsNode = jnode!["staffs"];
foreach(var staffNode in staffsNode!.AsArray())
{
Console.WriteLine($"{staffNode!["firstName"]!.GetValue<string>()} {staffNode!["lastName"]!.GetValue<string>()}");
}
- 静态方法 JsonNode.Parse 把JSON字符串或者流转换成 JsonNode 对象
- 使用["propertyName]或者["propertyIndex"]访问指定的节点,同时支持链式访问
- JsonNode 包含 GetValue 的泛型方法读取对应的值
- 除了 GetValue, JsonNode 还有 Deserialize 方法,可以将该节点反序列化成指定的对象。
- 对于数组节点,可以使用AsArray方法
Utf8JsonReader
byte[] bytes = Encoding.UTF8.GetBytes(str);
var reader = new Utf8JsonReader(bytes);
while (reader.Read())
{
if(reader.TokenType== JsonTokenType.PropertyName)
{
string? propertyName=reader.GetString();
switch (propertyName)
{
case "address":
case "staffs":
Console.WriteLine($"{propertyName}:");
break;
default:
reader.Skip();
string? propertyValue = reader.GetString();
Console.WriteLine($"{propertyName}:{propertyValue}");
break;
}
}
}
- Utf8JsonReader 其实是 JsonDocument 和 JsonNode 的底层方法
- 通过 TokenType 可以判断当前节点的类型,列入属性名,对象开始,对象结束,数组开始,数组结束等
- Reader包含GetString等一系列取值的方法
- Skip函数可以跳到下一个节点
总结
- JsonDocument 和 JsonNode 读取值的方式和灵活度差不多
- JsonDocument 是只读的, JsonNode 则可以修改
- JsonDocument 读取的速度比 JsonNode 快
- Utf8JsonReader 应该是速度最快的,不过使用起来就没那么方便,适合用来从JSON中提取特定的值。