使用 System.Text.Json 无类型方式读取JSON文件

c#

另一篇使用 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中提取特定的值。

参考

Related Posts

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注