打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
.NET 6 新特性 System.Text.Json 中的 Writeable DOM

.NET 6 新特性 System.Text.Json 中的 Writeable DOM 特性

Intro

在 .NET 6 Preview 4 中,微软加入了 JSON Node 的支持,我们可以动态的编辑一个 JSON 文档,一个可以修改的 JSON 文档,就像 Newtonsoft.Json 里的 JToken,这样我们就可以更加灵活的操作一个 JSON 了。


主要新增的 API 如下:


JsonNode: JSON 文档中的一个节点,对应 Newtonsoft.Json 里的 JToken

JsonObject: JSON 对象,对应 Newtonsoft.Json 里的 JObject

JsonArray: JSON 数组,对应 Newtonsoft.Json 里的 JArray

JsonValue: JSON 中的一个值,对应 Newtonsoft.Json 里的 JValue

Sample

你可以使用 JsonNode.Parse("") 来将一个 JSON 转换成一个 JsonNode 对象,可以看下面的示例:


// Parse a JSON object

JsonNode jNode = JsonNode.Parse(@"{""MyProperty"":42}");

int value = (int)jNode["MyProperty"];

Debug.Assert(value == 42);

// or

value = jNode["MyProperty"].GetValue<int>();

Debug.Assert(value == 42);

你可以通过 AsObject 将 JsonToken 转换为 JsonObject,通过 AsArray 转换为 JsonArray,通过 AsValue 转换为 JsonValue


对于 JsonNode 或者 JsonValue 可以强制类型转成成期望的类型,如下所示,或者可以通过 GetValue 来转成类型,类似于 Newtonsoft.Json 里的 Value<T>() 扩展方法



// Parse a JSON object

var jNode = JsonNode.Parse(@"{""MyProperty"":42}").AsObject();

var jValue = jNode["MyProperty"].AsValue();

var value = (int)jValue;

Debug.Assert(value == 42);


// or

value = jValue.GetValue<int>();

Debug.Assert(value == 42);

再来看一下修改 JSON 文档的一个示例:


var testObj = new {Name = "Ming", Age = 10};

var jsonString = JsonSerializer.Serialize(testObj);

var jsonNode = JsonNode.Parse(jsonString);

if (jsonNode is JsonObject jsonObject)

{

    jsonObject["Name"]?.GetValue<string>().Dump();

    jsonObject["Age"]?.GetValue<int>().Dump();


    jsonObject["Name"] = "Michael";

    jsonObject.ToJsonString().Dump();

}

Dump() 方法是封装的一个扩展方法,会把 value 打印到控制台,输出结果如下:


图片

接着我们来看一个 JSON 数组的示例:


var testArrayJsonString = JsonSerializer.Serialize(new[]

{

    new {Name = "Ming", Age = 10}, new {Name = "Alice", Age = 6}, new {Name = "Anna", Age = 8}

});

jsonNode = JsonNode.Parse(testArrayJsonString);

if (jsonNode is JsonArray jsonArray)

{

    jsonArray.Select(item => $"{item["Name"]}, {item["Age"]}")

        .StringJoin(Environment.NewLine)

        .Dump();

}

输出结果如下:


图片

接着我们再来看一个组合的示例:


var complexObj = new

{

    Name = "Mike", 

    Users = new[]

    {

        new {Name = "Alice", Age = 6}, 

        new {Name = "Anna", Age = 8}

    }

};

var jsonString = JsonSerializer.Serialize(complexObj);

jsonString.Dump();


var jsonNode = JsonNode.Parse(jsonString);

jsonNode?["Users"]?.AsArray().Select(item => $"--{item["Name"]}, {item["Age"]}")

    .StringJoin(Environment.NewLine)

    .Dump();

输出结果如下:


图片

另外一点想要提一下,就是现在有一点点 JSON Path 的支持,如果你有用过 SQL Server 里 JSON 查询的话一定对 JSON Path 有一定的了解,JSON Path 就像 XML Path,可以支持我们高效的找到对应的 JSON 节点,但是目前的支持并不好,也许正式如此,微软也并没有进行介绍,JsonNode 提供了 GetPath() 方法来获取当前 Node 对应的 JSON Path,但是现在对于根据 JSON Path 查询的支持还不行



jsonNode["Users"][0]["Name"].GetPath().Dump();

JsonNode.Parse(@"{""Prop1"":1}")["Prop1"].GetPath().Dump();

输出结果如下:


图片

我们可以使用 SQL Server 来测试一下 JSON Path 是否正确,测试脚本如下:


DECLARE @json NVARCHAR(MAX) = '{"Name":"Mike","Users":[{"Name":"Alice","Age":6},{"Name":"Anna","Age":8}]}';


SELECT JSON_VALUE(@json, '$.Users[0].Name')

查询结果如下:


图片

如果可以支持 jsonNode[jsonPath] 来直接定位到某一个 Node 就很棒了,期待以后能够支持~~


但是目前暂时不会支持,还有一些别的优先级高的 task 并且可能会有一些性能方面的影响,所以很有 .NET 6 不会有这个 feature,可以参考文末的 issue


More

JsonNode 相关的 API 在 Preview5 的时候发生了一个 breaking change,命名空间从 System.Text.Json.Node 变成了 System.Text.Json.Nodes,如果从 Preview4 升级的时候需要注意一下。


References

https://github.com/dotnet/runtime/issues/47649

https://github.com/dotnet/runtime/issues/51937

https://github.com/dotnet/runtime/pull/52200

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
c# 解析JSON的几种办法
Json
学习PHP中YAML操作扩展的使用
Newtonsoft.Json.dll序列化为json,null值自动过滤
Asp.net C# 使用Newtonsoft.Json 实现DataTable转Json格式数据
Json.net的高级用法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服