.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
總結
以上是生活随笔為你收集整理的.NET 6 新特性 System.Text.Json 中的 Writeable DOM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET Core with 微服务 -
- 下一篇: Hello Blazor:(2)集成Ta