.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

(0)

相关推荐

  • PHP中的日期相关函数(三)

    PHP中的日期相关函数(三) 之前我们已经介绍过了 PHP 的一些相关的日期操作对象,今天我们就来学习剩下的那些面向过程的使用方式.当然,如果是和 DateTime 类中相似的方法我们就不再进行介绍了 ...

  • PHP中的文件系统函数(二)

    PHP中的文件系统函数(二) 这次我们来学习的是一些不是太常用,但却也非常有用的一些函数.它们中有些大家可能见过或者使用过,有一些可能就真的没什么印象了.它们都是 PHP 中文件系统相关操作函数的一部 ...

  • ES6中常用的10个新特性讲解

    ECMAScript 6(ES6) 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ...

  • 何新读史杂记:历史中的虚拟国家——印度

    历史上从来没有过统一的希腊王国,也没有过统一的印度王国. 没有人能够说清楚印度或者巴基斯坦的民族究竟是什么民族.其实,印度和巴基斯坦地域的居民,历史上从来没有形成过统一的民族.当地的居民自古以来只有村 ...

  • 何新读史杂记: 历史中的虚拟国家——印度

    历史上从来没有过统一的希腊王国,也没有过统一的印度王国. 没有人能够说清楚印度或者巴基斯坦的民族究竟是什么民族.其实,印度和巴基斯坦地域的居民,历史上从来没有形成过统一的民族.当地的居民自古以来只有村 ...

  • 李勇:新《刑诉法解释》中的证据问题辨析

    [版权声明]版权归原作者所有,仅供学习参考之用,禁止用于商业用途,若来源标注错误或侵犯到您的权益,烦请告知,我们将立即删除 .来源:检察日报2021年4月30日第三版新<刑事诉讼法解释>中 ...

  • 瑞典国家电视台新冠死亡人数图表中神奇的Y轴

    瑞典从去年新冠疫情开始至今死于新冠肺炎的人数已经超过了1.4万人,死亡率每百万人口1369人,虽然没有美国的1755人高,但依然远高于北欧邻国丹麦的428人,芬兰的166人,挪威的141人,以及中国的 ...

  • 新《红楼梦》中的20个女角色,个个都是高颜值,你都还记得吗?

    第一位:蒋梦婕饰林黛玉 林黛玉是前世为三生石边的一株绛珠草,受神瑛侍者的甘露之惠,愿跟其下凡还尽眼泪.今世为巡盐御史林如海与贾府千金贾敏的独生女林黛玉,宝玉的姑表妹,寄居荣国府.她生性孤傲,多愁善感, ...

  • “26时のマスカレイド”全员确诊新冠肺炎,“わーすた”也中招

    日本女子偶像团体"わーすた",在5月4日宣布了其成员广川奈奈圣确诊新冠肺炎的消息. "わーすた"官方推文表示,广川奈奈圣在5月3日上午接受核酸检查结果为阳性反映 ...

  • 新冠口服疫苗正在进行中

    不用打针如何做到新冠免疫呢? 维尔茨堡大学的托马斯·鲁德尔(Thomas Rudel)教授带领自己的团队正在研究新冠口服疫苗. 鲁德尔教授介绍了自己的项目: "我们在现有的针对伤寒的疫苗细菌 ...

  • 动点汽车:造车新势力陆续增员中,战场已经进入到白热化阶段

    造车已经是一个新的赛道,这个赛道将孕育极大的机遇.除了已经在市场上卖车的几个新造车势力,现在陆续有新的成员加入进来.这些成员都分别处于不同的领域,或者是相关的产业链,而参与到新能源车这个主赛道,无论是 ...