以往在 Json.NET 有 JToken
、JObject
、JArray
、JValue
這些類別,可以讓我們在反序列化 JSON 的時候,不必一定要為其結構新增對應的型別,2021 年 11 月 .NET 6 釋出之後,內建的 System.Text.Json 也隨之升級,增加了 JsonNode
、JsonObject
、JsonArray
、JsonValue
,與 Json.NET 的那四個類別相對應,那我想要在 .NET Framework 使用 System.Text.Json 行不行?
先說答案,是「可以
」的,手上有一個 .NET Framework 的專案需要 JSON 的序列化/反序列化,正好拿來練練手,但是在眾多文章皆強調是 .NET Core 3.0+/.NET 5+
的開發環境之下,一開始擔心會不會 .NET Framework 不支援,抱著姑且一試的心態安裝看看,事實證明我多慮了。
System.Text.Json 雖然已經內建在 .NET Core 3.0+/.NET 5+ 裡面,但是它也是做為一個獨立套件存在,根據它的相依條件來看,只要是 .NET Framework 4.6.1 以上的版本,應該是可以安裝使用的,如果要使用新的 JsonNode、JsonObject、...這些類別的話,System.Text.Json 的版本則要 6.0.0 以上才有,6.0.0 之下是沒有的。
接下來我們就寫一段程式來測試看看,System.Text.Json 在 .NET Framework 上的一些基本功能有沒有什麼問題?
// 序列化/WriteIndented/CamelCase
var jsonString = JsonSerializer.Serialize(
new { Id = 1, Name = "Johnny", Birthday = new DateTime(1984, 7, 17) },
new JsonSerializerOptions { WriteIndented = true });
// 反序列化/AnonymousType/PropertyNameCaseInsensitive
var obj = JsonSerializer.Deserialize(
jsonString,
new { Id = default(int), Name = default(string), Birthday = default(DateTime) }.GetType(),
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
// 反序列化/JsonNode/Parse
var jsonNode = JsonNode.Parse("{\"jobId\":\"8b9fd0b3-1ec9-4792-83c2-713ccfe7e34b\",\"lastUpdatedDateTime\":\"2022-09-08T09:09:57Z\",\"createdDateTime\":\"2022-09-08T09:09:56Z\",\"expirationDateTime\":\"2022-09-09T09:09:56Z\",\"status\":\"succeeded\",\"errors\":[],\"displayName\":\"4b3fa34f-2242-439a-82ac-dff0bc8b8573\",\"tasks\":{\"completed\":1,\"failed\":0,\"inProgress\":0,\"total\":1,\"items\":[{\"kind\":\"CustomSingleLabelClassificationLROResults\",\"lastUpdateDateTime\":\"2022-09-08T09:09:57.6643241Z\",\"status\":\"succeeded\",\"results\":{\"documents\":[{\"id\":\"d323e6e8-fa09-443d-b2e8-c92e429d30e1\",\"class\":[{\"category\":\"gamble\",\"confidenceScore\":0.98}],\"warnings\":[]}],\"errors\":[],\"projectName\":\"article-classification\",\"deploymentName\":\"article-prediction\"}}]}}");
// JsonNode/GetValue<string>()
var jobId = jsonNode["jobId"].GetValue<string>();
// JsonNode/GetValue<DateTime>();
var lastUpdatedDateTime = jsonNode["lastUpdatedDateTime"].GetValue<DateTime>();
// JsonNode/AsObject
var jsonObj = jsonNode.AsObject();
// JsonObject/TryGetPropertyValue
if (jsonObj.TryGetPropertyValue("createdDateTime", out var outJsonNode))
{
var createdDateTime = outJsonNode.GetValue<DateTime>();
}
// JsonNode/AsArray
var items = jsonNode["tasks"]["items"].AsArray();
var documents = items[0]["results"]["documents"].AsArray();
// JsonNode/AsValue/TryGetValue()
if (documents[0]["id"].AsValue().TryGetValue(out string documentId))
{
}
現在還是有很多 .NET 的開發者還在觀望 System.Text.Json,在台灣 .NET 技術愛好者俱樂部有一篇貼文及底下留言,就有很多朋友分享 System.Text.Json 的使用經驗,不過回歸到單純處理 JSON 資料的序列化/反序列化,我認為 System.Text.Json 已足以勝任,雖然對於 .NET Framework 的應用程式來講,一樣都要額外安裝套件,不過 System.Text.Json 在效能上略勝 Json.NET 一籌,各位朋友不妨嘗試看看。