網路城邦
上一篇 回創作列表 下一篇   字體:
System.Text.Json 的初步接觸
2026/07/24 11:44:55瀏覽3|回應0|推薦0

在微軟官方網站上檢視.NET 8新功能時,看到一句話:「.NET 8 中的  System.Text.Json 序列化和還原序列化功能進行許多改進。」當下腦袋充滿了各種問號,因為當時的我對Json的認知都還停留在Newtonsoft.Json這套件上,後來上網查了一下才知道:微軟早在.NET Core 3.0開始就內建 System.Text.Json 做為預設Json處理核心,也是為了擺脫對Json.Net的依賴。

記得早期有一段時期,.NET Framework 4點多的時候,曾經因為發佈出來的程式版本與config中指定的Newtonsoft.Json版本不合而去更新Newtonsoft.Json組件、或追加調整config指定版本;現在回想起來,如果這部分可以直接採用內建套件、就不會再擔心發生版本差異的問題了。

發展至今,System.Text.Json是否可以完整取代Newtonsoft.Json我不知道,但我針對性的以公司內常用的Json功能進行檢查:幾乎可以說是換掉namespace命名空間即可;而少部分有差異的地方才需要調整程式碼。

在此先補充說明:此篇文章僅針對公司內常用功能進行檢查,不做效能判斷,一來是公司內較少需要大量且頻繁地進行Json資料轉換,其次兩種套件的效能比較早在.NET Core 3.0的版本時就有,僅附網址提供參考:https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/?WT.mc_id=DOP-MVP-37580

開發程式中約有八到九成使用Json的部分都是序列化、和反序列化,這部分只要改參考即可:

using System.Text.Json;

var jsonString = "{\"Name\":\"Small Small Fish\",\"Age\":20, \"Sex\":1, \"SexText\":\"Female\" , \"Desc\":\"non-marine fish\"  }";

Console.WriteLine(jsonString);

 

var student = JsonSerializer.Deserialize(jsonString);

var text = JsonSerializer.Serialize(student);

預設的序列化和反序列化功能有以下兩點特徵:

  1. Enum屬性預設是轉int
  2. 不會自動縮排

在使用Serialize的過程中,最常注意的就是縮排,預設沒有自動縮排這一點對我來說是比較好,因為比較節省空間、尤其是寫Log的時候,但對有的人來說並不友善,因為有了縮排才好檢視。

在這方面,System.Text.Json與Newtonsoft.Json不同,使用的物件屬性名稱有一點差異、需要微調程式碼。

Newtonsoft.Json是使用JsonSerializerSettings、其屬性是Formatting為enum:

var setting = new JsonSerializerSettings 

{

 Formatting = Newtonsoft.Json.Formatting.None

};

JsonConvert.SerializeObject(value, setting);

System.Text.Json則是使用JsonSerializerOptions、其屬性是WriteIndented為bool:

var options = new JsonSerializerOptions

{

 WriteIndented = true

};

var text2 = JsonSerializer.Serialize(student, options);

除此之外,常見且比較有可能用到的諸如:enum屬性不是轉為int而是轉為string的話、或是屬性名稱有所差異等,都可以依靠追加attribute來支援的功能:

public enum StudentSex

{

 Male = 0, 

 Female = 1

}

public class Student

{

 public string Name { get; set; }

 public int Age { get; set; }

 public StudentSex Sex { get; set; }

 [JsonConverter(typeof(JsonStringEnumConverter))]

 public StudentSex SexText { get; set; }

 public int No { get; set; }

 [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]

 public string Tag { get; set; }

 [JsonIgnore(Condition = JsonIgnoreCondition.Never)]

 public string Address1 { get; set; }

 [JsonIgnore(Condition = JsonIgnoreCondition.Always)]

 public string Address2 { get; set; }

 [JsonPropertyName("Desc")]

 public string Description { get; set; }

}

如此一來,同樣是enum,但Sex為數值、SexText則為文字;且程式中Description的屬性在Json字串內則是Desc。

var jsonString = "{\"Name\":\"Small Small Fish\",\"Age\":20, \"Sex\":1, \"SexText\":\"Female\", \"Address2\": \"test\", \"Tag\": null, \"No\": 0, \"Desc\":\"non-marine fish\"  }";

var student = JsonSerializer.Deserialize(jsonString);

var text1 = JsonSerializer.Serialize(student, JsonSerializerOptions.Default);

Console.WriteLine("serialize by default:");

Console.WriteLine(text1);

Console.WriteLine();

var options = new JsonSerializerOptions

{

 ReadCommentHandling = JsonCommentHandling.Skip,

    WriteIndented = true,

    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,

};

var text2 = JsonSerializer.Serialize(student, options);

Console.WriteLine("serialize by options:");

Console.WriteLine(text2);

程式執行結果:

其中,Ignore忽略轉換功能比較特殊,可透過attribute指定特定屬性支援、也可以直接透過序列化設定進行指定,而且除了null以外也可以指定default值就進行忽略(例如int的default值為0),或是Always一直忽略轉換該屬性、Never一直不能忽略該屬性。

雖然System.Text.Json我是在Net8推出之後才開始接觸,但文中上述程式碼卻並非都是.NET 8才可以使用,至少.NET 6運作無誤。

Reference:

  1. https://blog.poychang.net/using-json-serializer-with-system-text-json/
  2. https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/ignore-properties
  3. https://blog.darkthread.net/blog/system-text-json/
( 知識學習其他 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=acaj2018&aid=191558322