依微軟的計劃,System.Text.Json 應取代 Json.NET,成為 .NET Core/.NET 5+ 奧林匹克指定 JSON 程式庫。System.Text.Json 主打輕巧高效能,但畢竟發展時間尚短,與身經百戰的老將 Json.NET 相比,在功能完整性及可擴充性上仍有點「嫩」。其中我覺得最不便的地方是缺少像 Json.NET 一樣的 JObjec/JArray 物件模型,無法動態巡覽 JSON 屬性或修改內容,更甭提整合 dynamic 動態型別的花式應用

好消息! .NET 6 起,System.Text.Json 補強了這段,加入 JsonNodeJsonObjectJsonArrayJsonValue 等型別,對映到 Json.NET 的 JToken、JObject、JArray、JValue,允許開發者以物件模型方式建構 JSON 文件,或是將 JSON 文件轉為物件資料結構,進行增刪修改或屬性巡覽,有了這項武器,處理 JSON 文件就更方便了。

多說無益,直接來段威力展示:

using System.Text.Json.Nodes;
using System.Text.Json;

// 建立 JSON
var avatar = new JsonObject {
    ["Id"] = "A001",
    ["Name"] = "Jeffrey",
    ["Extra"] = "Prop To Remove",
    ["Equipments"] = new JsonArray("Shield", "Sword", "Bottle")
};
// 動態指定屬性
avatar["Score"] = 32767;
// 加入物件屬性
avatar["Pet"] = new JsonObject {
    ["Name"] = "Spot",
    ["Exp"] = 255
};
// 移除屬性
avatar.Remove("Extra");
// 對 JsonArray 進行操作
var array = avatar["Equipments"]!.AsArray();
array.Remove(array.Single(o => o?.GetValue<string>() == "Bottle"));
array.Insert(0, "Bag");

var json = avatar.ToJsonString(new JsonSerializerOptions{
    WriteIndented = true
});
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(json);

Console.ForegroundColor = ConsoleColor.Blue;
// 由 JSON 還原回 JObject
var restored = JsonNode.Parse(json)!.AsObject();
// 列舉所有屬性
foreach (var prop in restored) {
    var pn = prop.Key;
    // 測試屬性型別
    if (prop.Value is JsonObject) 
        Console.WriteLine($"{pn} is JsonObject");
    else if (prop.Value is JsonArray) 
        Console.WriteLine($"{pn} is JsonArray, length={prop.Value.AsArray().Count()}");
    // 使用 TryGetValue<T> 嘗試取值
    else if (prop.Value?.AsValue().TryGetValue<int>(out var i) ?? false) 
        Console.WriteLine($"{pn} is int: {i}");   
}
Console.ResetColor();

執行結果:

Introduce to the new feature of System.Text.Json, writable DOM API.


Comments

# by ByTim

您好,想問一下這一段,var array = avatar["Equipments"]!.AsArray();,!.這個是什麼,我沒用過,我有用過int aaa=Row?.(int欄位) ?? 0。

# by Jeffrey

to ByTim, .NET 6 預設 Nullable 檢查,對所有可能出現 Null 的場合要求你確認或調整,嚴格來說是好事,所以我沒選擇關閉檢查,而是加上 ! 告知 Compiler,「對,拎杯這裡就是要允許 null」,或是「你懂什麼,這裡不可能是 null」。 延伸閱讀: https://www.facebook.com/darkthread.net/posts/498779464951825

Post a comment