相信大家都發現 JSON 格式已經取代過去的 XML 成為資料交換的首選,在 ASP.NET Core 3.0 專案範本設定檔也是使用 JSON 作為設定檔的格式,並內建廣受好評的 Json.NET 做為處理 JSON 格式的函式庫,依存放在 Microsoft.AspNetCore.App 無須在透過 Nuget 另外下載,但老牌的 Json.NET 雖然好用但也相對的存在過去一些沉重的包袱,為了提高性能 ASP.NET Core 3.0 Preview 5 開始提供 System.Text.Json namespace 提供多組 API 讓開發者處理 JSON 更為方便,這篇就來簡單 ASP.NET Core 3.0 開始有的新朋友 System.Text.Json API 的基本使用與操作,若有問題或是錯誤的地方歡迎網路的高手大大給予指導。
介紹
使用前可以先參考使用說明書,.NET Blog 文章 : Try the new System.Text.Json APIs 有針對此新的 Json API 做詳細的介紹與說明,除了文章另外好棒棒的提供影片向開發者介紹新朋友的故事
影片內容約 20 分鐘,適合上班交通途中觀看使用,小弟不專業的筆記重點整理如下 :
如有興趣可以直接觀看影片,或是參考黑暗大文章 System.Text.Json! 有更專業詳細的介紹
安裝
使用前需要先透過 nuget 進行下載的動作,因此到 nuget package manager 搜尋並下載 system.text.json
下載過程中會提示安裝後的變更,可以看到目前還是 RC1 階段尚未正式 release
當然也可以透過 Nuget Package Console 輸入下列指令
Install-Package System.Text.Json -Version 4.6.0-rc1.19456.4安裝完畢之後到專案檔底下確認是否有安裝成功
<ItemGroup> <PackageReference Include="System.Text.Json" Version="4.6.0-rc1.19456.4" /> </ItemGroup>
使用
安裝完畢接著可以進行簡單的功能測試,以下就根據目前 System.Text.Json 所提供的功能 Deserialization、Serialize、JsonDocument、JsonTokenType 做基本使用的介紹,在開始前為了方便大家理解建立一個簡單的 book 類別,其中包含 ISBN、Name、Price 三個屬性,方便後續 sample 使用
public class Book { public int ISBN { get; set; } public string Name { get; set; } public double Price { get; set; } }
Serialize 序列化
將類別轉為 JSON 字串的過程叫做 序列化,在 System.Text.Json 序列化使用 JsonSerializer.Serialize 方法,就可以將指定類別序列化的動作
static void Main(string[] args) { var comic = new Book() { ISBN = 9487, Name = "One Piece Comic - 934", Price = 120 }; Console.WriteLine(JsonSerializer.Serialize(comic)); }以上代碼輸出 JSON 格式會是
{"ISBN":9487,"Name":"One Piece Comic - 934","Price":120}Serialize 也提供多載的方法,可以透過 JsonSerializerOptions 指定序列化的參數設定,舉例來說上述範例類別序列化後預設會將 JSON 字串進行最小化 minify 動作,因此編排會是一行呈現,若是要取消此設定可以調整 WriteIndented,則可看到較容易閱讀的 JSON 格式
JsonSerializer.Serialize(comic, new JsonSerializerOptions() { WriteIndented = true })序列化的 JSON 格式就會變成如下內容,方便開發者閱讀
{ "ISBN": 9487, "Name": "One Piece Comic - 934", "Price": 120 }更多關於 JsonSerializerOptions 的設定資訊可以參考 MSDN 官方說明文件 : 傳送門
Deserialize 反序列化
將字串解析成物件的內容稱為 反序列化,反序列化可以透過 JsonSerializer.Deserialize 方法達到,話不多說直接上 Code
var jsonString = @"{""ISBN"":9487,""Name"":""One Piece Comic - 934"",""Price"":120}"; var book = JsonSerializer.Deserialize<Book>(jsonString); var comic = new Book() { ISBN = 9487, Name = "One Piece Comic - 934", Price = 120 }; Console.WriteLine($"ISBN : {book.ISBN}"); Console.WriteLine($"Name : {book.Name}"); Console.WriteLine($"Price: {book.Price}");可以看到輸出結果如下
ISBN : 9487 Name : One Piece Comic - 934 Price: 120如果某個物件屬性希望在反序列化時被忽略,可以在屬性加上 [JsonIgore] attribute 忽略,在反序列化時就不會 bind 該屬性值;或是使用 [JsonPropertyName] 自訂 JSON 屬性名稱可以使用
public class Book { [JsonIgnore] public int ISBN { get; set; } [JsonPropertyName("Name")] public string BookName { get; set; } public double Price { get; set; } }輸出如下
ISBN : 0 BookName : One Piece Comic - 934 Price: 120另外在序列化與反序列化在 System.Text.Json 都有提供 Async 方法來提高其執行效率
讀取 Json Dom - JsonDocument
有時需求是希望讀取 JSON 特定屬性資料,可以透過 JsonDocument 可以輕易的讀取 JSON 屬性與值資訊,以下列例子來說希望取得兩本書的 Price 總和,可以使用 JsonDocument.Parse 讀取 JSON 字串內容,在透過 GetProperty 搜尋要找尋的屬性名稱並轉換為需要的型別,最後在做加總的動作
static void Main(string[] args) { var json = @"[ { ""ISBN"": 9487, ""Name"": ""One Piece Comic - 934"", ""Price"": 120 }, { ""ISBN"": 5566, ""Name"": ""One Piece Comic - 937"", ""Price"": 546 }, ]"; using (JsonDocument document = JsonDocument.Parse(json)) { var sumOfAllTemperatures = 0; foreach (var element in document.RootElement.EnumerateArray()) { var price = element.GetProperty("Price").GetInt16(); sumOfAllTemperatures += price; } Console.WriteLine($"Total Price : {sumOfAllTemperatures}"); }可以看到輸出結果如下
Total Price : 666另外有時讀取/要轉換的 JSON 的內容可能會多包含一個 "," 符號,這種情境下可以透過 JsonDocumentOptions 設定進行調整,設定其 AllowTrailingCommas 屬性為 true,則可以避免此狀況發生。
WriteJson - Utf8JsonWriter
有讀取 JSON 的 API 當然也提供寫入 JSON 檔案的 API,寫入可以透過 Utf8JsonWriter 方法完成,話不多說直接上 Code,在一開始設定 JSON 格式為好閱讀的排版方式,接著在使用 Utf8JsonWriter 將上面一直提到的 Book 類別結構使用指定型別方式寫入,例如 ISBN 就是使用 WriteNumber、書名使用 WriteString 等內建提供的 API 方法達到需求
static void Main(string[] args) { var options = new JsonWriterOptions { Indented = true }; using (var stream = new MemoryStream()) { using (var writer = new Utf8JsonWriter(stream, options)) { writer.WriteStartObject(); writer.WriteNumber("ISBN", 9487); writer.WriteString("Name", "One Piece Comic - 934"); writer.WriteNumber("Price", 777); writer.WriteEndObject(); } string json = Encoding.UTF8.GetString(stream.ToArray()); Console.WriteLine(json); } }可以看到輸出結果如下
{ "ISBN": 9487, "Name": "One Piece Comic - 934", "Price": 777 }
感想
這篇文章介紹了在 System.Text.Json 的安裝與使用情境,序列化(Serializer)、反序列化(Deserialize)、JSON 格式的讀 (JsonDocument) 與寫 (Utf8JsonWriter) 的 API 應用,在影片與文章中也有提到 API 將會持續開發中,在文章後面也有提到效能與 Json.NET 至少提升 1.3 ~ 5 倍的速度,但對於 JSON 格式的支援一定不如老牌的 Json.NET 來的齊全,希望在 ASP.NET Core 3.0 正式發布時可以支援更多功能與應用,對開發者來說也是一大家福音 :)
參考
Try the new System.Text.Json APIs
Channel 9 : Try the new System.Text.Json APIs!
SerializerProgrammingModel.md
The future of JSON in .NET Core 3.0
Breaking changes to Microsoft.AspNetCore.App in 3.0
Procesar JSON con System.Text.Json
. These types don't yet support plain old CLR object (POCO) serialization and deserialization.
回覆刪除這點可能要注意一下