只有累積,沒有奇蹟

2019年9月17日 星期二

[NETCore] 初探 ASP.NET Core 3.0 新朋友 - System.Text.Json

前言
相信大家都發現 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 分鐘,適合上班交通途中觀看使用,小弟不專業的筆記重點整理如下 :

  • MVP (Minimum Viable Product) 概念出發,最小可行性與常用的需求出發來設計 API
  • 目的是提供 高效能的 Json API
  • 使用 .NET Core 2.1 Span<T> 提高性能,與 Json.NET 相比記憶體使用量較低
  • ASP.NET Core 3.0 之後為內建,3.0 之前是使用 Json.NET 
  • 使用 UTF-8 讀取/寫入 Json 文件,( HTTP 使用 UTF-8 編碼,JSON.NET 預設是使用 UTF-16),避免轉碼與記憶體浪費

  • 如有興趣可以直接觀看影片,或是參考黑暗大文章 System.Text.Json! 有更專業詳細的介紹

    安裝
    使用前需要先透過 nuget 進行下載的動作,因此到 nuget package manager 搜尋並下載 system.text.json  
    下載過程中會提示安裝後的變更,可以看到目前還是 RC1 階段尚未正式 release 
    當然也可以透過 Nuget Package Console 輸入下列指令
    1. Install-Package System.Text.Json -Version 4.6.0-rc1.19456.4
    安裝完畢之後到專案檔底下確認是否有安裝成功
    1. <ItemGroup>
    2. <PackageReference Include="System.Text.Json" Version="4.6.0-rc1.19456.4" />
    3. </ItemGroup>

    使用
    安裝完畢接著可以進行簡單的功能測試,以下就根據目前 System.Text.Json 所提供的功能 Deserialization、Serialize、JsonDocument、JsonTokenType 做基本使用的介紹,在開始前為了方便大家理解建立一個簡單的 book 類別,其中包含 ISBN、Name、Price 三個屬性,方便後續 sample 使用 
    1. public class Book
    2. {
    3. public int ISBN { get; set; }
    4. public string Name { get; set; }
    5. public double Price { get; set; }
    6. }

    Serialize 序列化
    將類別轉為 JSON 字串的過程叫做 序列化,在 System.Text.Json 序列化使用  JsonSerializer.Serialize  方法,就可以將指定類別序列化的動作
    1. static void Main(string[] args)
    2. {
    3. var comic = new Book()
    4. {
    5. ISBN = 9487,
    6. Name = "One Piece Comic - 934",
    7. Price = 120
    8. };
    9.  
    10. Console.WriteLine(JsonSerializer.Serialize(comic));
    11. }
    以上代碼輸出 JSON 格式會是
    1. {"ISBN":9487,"Name":"One Piece Comic - 934","Price":120}
    Serialize 也提供多載的方法,可以透過 JsonSerializerOptions 指定序列化的參數設定,舉例來說上述範例類別序列化後預設會將 JSON 字串進行最小化 minify 動作,因此編排會是一行呈現,若是要取消此設定可以調整 WriteIndented,則可看到較容易閱讀的 JSON 格式
    1. JsonSerializer.Serialize(comic, new JsonSerializerOptions()
    2. {
    3. WriteIndented = true
    4. })
    序列化的 JSON 格式就會變成如下內容,方便開發者閱讀
    1. {
    2. "ISBN": 9487,
    3. "Name": "One Piece Comic - 934",
    4. "Price": 120
    5. }
    更多關於 JsonSerializerOptions 的設定資訊可以參考 MSDN 官方說明文件 : 傳送門 

    Deserialize 反序列化
    將字串解析成物件的內容稱為 反序列化,反序列化可以透過  JsonSerializer.Deserialize  方法達到,話不多說直接上 Code
    1. var jsonString = @"{""ISBN"":9487,""Name"":""One Piece Comic - 934"",""Price"":120}";
    2.  
    3. var book = JsonSerializer.Deserialize<Book>(jsonString);
    4.  
    5. var comic = new Book()
    6. {
    7. ISBN = 9487,
    8. Name = "One Piece Comic - 934",
    9. Price = 120
    10. };
    11.  
    12. Console.WriteLine($"ISBN : {book.ISBN}");
    13. Console.WriteLine($"Name : {book.Name}");
    14. Console.WriteLine($"Price: {book.Price}");
    可以看到輸出結果如下
    1. ISBN : 9487
    2. Name : One Piece Comic - 934
    3. Price: 120
    如果某個物件屬性希望在反序列化時被忽略,可以在屬性加上  [JsonIgore]  attribute 忽略,在反序列化時就不會 bind 該屬性值;或是使用  [JsonPropertyName]  自訂 JSON 屬性名稱可以使用
    1. public class Book
    2. {
    3. [JsonIgnore]
    4. public int ISBN { get; set; }
    5. [JsonPropertyName("Name")]
    6. public string BookName { get; set; }
    7. public double Price { get; set; }
    8. }
    輸出如下
    1. ISBN : 0
    2. BookName : One Piece Comic - 934
    3. Price: 120
    另外在序列化與反序列化在 System.Text.Json 都有提供 Async 方法來提高其執行效率

    讀取 Json Dom - JsonDocument
    有時需求是希望讀取 JSON 特定屬性資料,可以透過 JsonDocument 可以輕易的讀取 JSON 屬性與值資訊,以下列例子來說希望取得兩本書的 Price 總和,可以使用  JsonDocument.Parse  讀取 JSON 字串內容,在透過 GetProperty 搜尋要找尋的屬性名稱並轉換為需要的型別,最後在做加總的動作
    1. static void Main(string[] args)
    2. {
    3. var json = @"[
    4. {
    5. ""ISBN"": 9487,
    6.  
    7. ""Name"": ""One Piece Comic - 934"",
    8. ""Price"": 120
    9.  
    10. },
    11. {
    12. ""ISBN"": 5566,
    13. ""Name"": ""One Piece Comic - 937"",
    14. ""Price"": 546
    15. },
    16. ]";
    17.  
    18. using (JsonDocument document = JsonDocument.Parse(json))
    19. {
    20. var sumOfAllTemperatures = 0;
    21.  
    22. foreach (var element in document.RootElement.EnumerateArray())
    23. {
    24. var price = element.GetProperty("Price").GetInt16();
    25.  
    26. sumOfAllTemperatures += price;
    27. }
    28.  
    29. Console.WriteLine($"Total Price : {sumOfAllTemperatures}");
    30. }
    可以看到輸出結果如下
    1. Total Price : 666
    另外有時讀取/要轉換的 JSON 的內容可能會多包含一個 "," 符號,這種情境下可以透過 JsonDocumentOptions 設定進行調整,設定其 AllowTrailingCommas 屬性為 true,則可以避免此狀況發生。

    WriteJson - Utf8JsonWriter
    有讀取 JSON 的 API 當然也提供寫入 JSON 檔案的 API,寫入可以透過  Utf8JsonWriter  方法完成,話不多說直接上 Code,在一開始設定 JSON 格式為好閱讀的排版方式,接著在使用 Utf8JsonWriter 將上面一直提到的 Book 類別結構使用指定型別方式寫入,例如 ISBN 就是使用 WriteNumber、書名使用 WriteString 等內建提供的 API 方法達到需求
    1. static void Main(string[] args)
    2. {
    3. var options = new JsonWriterOptions
    4. {
    5. Indented = true
    6. };
    7.  
    8. using (var stream = new MemoryStream())
    9. {
    10. using (var writer = new Utf8JsonWriter(stream, options))
    11. {
    12. writer.WriteStartObject();
    13. writer.WriteNumber("ISBN", 9487);
    14. writer.WriteString("Name", "One Piece Comic - 934");
    15. writer.WriteNumber("Price", 777);
    16. writer.WriteEndObject();
    17. }
    18.  
    19. string json = Encoding.UTF8.GetString(stream.ToArray());
    20. Console.WriteLine(json);
    21. }
    22. }
    可以看到輸出結果如下
    1. {
    2. "ISBN": 9487,
    3. "Name": "One Piece Comic - 934",
    4. "Price": 777
    5. }

    感想
    這篇文章介紹了在 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

    Related Posts:

    • [NETCore] 初探 ASP.NET Core 3.0 新朋友 - System.Text.Json前言 相信大家都發現 JSON 格式已經取代過去的 XML 成為資料交換的首選,在 ASP.NET Core 3.0 專案範本設定檔也是使用 JSON 作為設定檔的格式,並內建廣受好評的 Json.NET 做為處理 JSON 格式的函式庫,依存放在 Microsoft.AspNetCore.App 無須在透過 Nuget 另外下載,但老牌的 Json.NET 雖然好用但也相對的存在過去一些沉重的包袱,為了提高性能&n… Read More
    • [Tool] JSON Viewer Awesome - 理解 JSON 結構的好幫手介紹 Json (JavaScript Object Notation) 是一種輕量級的資料交換格式,方便開發者在開發與閱讀,與早期使用的 XML 相比在進行資料交換時,沒有其多餘的格式可以降低傳輸封包的大小,增加其封包傳遞的效率 (...不自覺透露出年紀了),這些都是給電腦看不是給人看得,如果開發者需要確認 Json 元素的值是否正常時,就另外需要透過工具達到,今天要分享的是 Chrome 擴充套件 - JSON Viewer Awe… Read More
    • [NETCore] ASP.NET Core 設定 JSON 序列化格式前言 JSON.NET 是十分好用的套件,在 ASP.NET Core 1.0 開始內建 JSON.NET方便開發者快速使用,建立 ASP.NET Core 範本專案時會在  ConfigureServices  中的 addMVC 就可以開始使用,這篇介紹如何在 ASP.NET Core 中定義 JSON.NET 統一輸出格式的設定,若有問題歡迎留言一起討論。 範例代碼 首先建立 ASP.NET C… Read More
    • [NET] 檢查字串是否為 Json 格式前言 在開發時很常使用到 Json 格式作為設定檔,舉例來說在 ASP.NET Core 設定檔預設也是使用 Json 格式,系統開發中也會將一些常用的設定放在 Json 方便調整,在 ASP.NET 讀取 Json 最常用到的是 Json.Net 套件,使用上可以很方便地將字串轉為定義的類別內容,這篇就來分享怎麼用 Json.net 來判斷要轉換的文字字串是否為 Json 格式,若有問題歡迎留言一起討論。 代碼 首先先下載 Json.Ne… Read More

    1 則留言:

    1. . These types don't yet support plain old CLR object (POCO) serialization and deserialization.
      這點可能要注意一下

      回覆刪除

    Copyright © 2025 m@rcus 學習筆記 | Powered by Blogger

    Design by Anders Noren | Blogger Theme by NewBloggerThemes.com