[小菜一碟] .NET Framework 能不能用新版 System.Text.Json 的 JsonNode、JsonObject、JsonArray、JsonValue?

  • 1454
  • 0
  • C#
  • 2022-09-22

以往在 Json.NETJTokenJObjectJArrayJValue 這些類別,可以讓我們在反序列化 JSON 的時候,不必一定要為其結構新增對應的型別,2021 年 11 月 .NET 6 釋出之後,內建的 System.Text.Json 也隨之升級,增加了 JsonNodeJsonObjectJsonArrayJsonValue,與 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 一籌,各位朋友不妨嘗試看看。

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學