【C# 序列化】Json序列化器


從 Newtonsoft.Json 遷移到 System.Text.Json

 

一.寫在前面

System.Text.Json 是 .NET Core 3 及以上版本內置的 Json 序列化組件,剛推出的時候經常看到踩各種坑的吐槽,現在經過幾個版本的迭代優化,提升了易用性,修復了各種問題,是時候考慮使用 System.Text.Json 了。本文將從使用層面來進行對比。

System.Text.Json 在默認情況下十分嚴格,避免進行任何猜測或解釋,強調確定性行為。比如:字符串默認轉義,默認不允許尾隨逗號,默認不允許帶引號的數字等,不允許單引號或者不帶引號的屬性名稱和字符串值。 該庫是為了實現性能和安全性而特意這樣設計的。Newtonsoft.Json 默認情況下十分靈活。

關於性能,參考 Incerry 的性能測試:.NET性能系列文章二:Newtonsoft.Json vs. System.Text.Json ,如果打算使用 .NET 7 不妨考慮一下 System.Text.Json。

Newtonsoft.Json 使用 13.0.2 版本,基於 .NET 7。

 

兩者對比着使用,請看 https://www.cnblogs.com/stulzq/p/17118904.html

命名空間

System.Text.Json:默認情況下,System.Text.Json使用運行時反射來收集它需要訪問序列化和反序列化對象的屬性的元數據。作為一種替代方法,System.Text.Json 6.0可以使用c#源生成器特性來提高性能,減少私有內存的使用,並簡化程序組裝,從而減少應用程序大小。例如在asp.net中可以讀取 XML、JSON 直接生成 C# 代碼參與編譯,DTO 編寫全自動化都是沒問題的。編譯時反射 - 0 運行時開銷。

.NET 6 中的 System.Text.Json 已做了許多改進,因此它現在是一個“工業強度”的序列化解決方案。

源生成器

.NET 6 為 添加了新的源生成器。 源生成可與 JsonSerializer 配合使用,並且可以通過多種方式進行配置。 它可以提高性能、減少內存使用量並便於程序集剪裁。 有關詳細信息,請參閱如何在 System.Text.Json 中選擇反射或源生成以及如何在 System.Text.Json 中使用源生成


System.Text.Json.Nodes
System.Text.Json.Serialization

 

 JSON簡介

JSON 是一種數據格式,已成為 XML 的流行替代品。它簡單而整潔,語法類似於 JavaScript 對象。實際上,術語 JSON 代表 JavaScript Object Notation。.NET 的最新版本為處理 JSON 數據提供了內置支持。

System.Text.Json 命名空間提供高性能、低分配的功能來處理 JSON 數據。這些功能包括將對象序列化為 JSON 並將 JSON 反序列化為對象。它還提供用於創建內存中文檔對象模型 (DOM) 的類型,用於訪問 JSON 文檔中的任何元素,提供數據的結構化視圖。

支持 System.Runtime.Serialization 特性。System.Text.Json 中不支持 System.Runtime.Serialization 命名空間中的特性。

詳細請查看 【C# 序列化】 JSON-在.net croe中的應用

Text.Json支持的格式

JSON 數據的書寫格式是:名稱/值對,數據由逗號分隔。.net core  對json 的處理默認使用駝峰式,
JSON 值可以是:
數字(整數或浮點數)
字符串(在雙引號中)
邏輯值(true 或 false)
數組(在方括號中)[,]
對象(在花括號中){}
null

 

public class Serializeables
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Ser = "first ser";
public bool Sers = true;
public bool[] Serbool = { true ,true,true};
public List<SerrializePeople> SerList = new();
}
//輸出
/*{
    "Date": "0001-01-01T00:00:00+00:00",
    "TemperatureCelsius": 0,
    "Ser": "first ser",
    "Sers": true,
    "Serbool": [true, true, true],
    "SerList": [{
        "Person": null
    }, {
        "Person": null
    }]
}
*/

 Json序列化器 簡介

 

 

 

 

 

 

功能

了具有以下功能的JsonSerializer

  • 支持對簡單傳統CLR對象(POCO)、基元類型、集合進行序列化和反序列化;
  • 內置的異步序列化和反序列化;
  • 原生處理UTF-8數據;
  • 反序列化可選是否區分大小寫;
  • 使用JsonNamingPolicy.CamelCase的駝峰命名策略;
  • 使用JsonNamingPolicy指定自定義命名策略;
  • 轉義的JSON數據反序列化;
  • 序列化時可選的最小字符轉義;
  • 序列化時忽略空值;
  • 反序列化時忽略注釋;
  • 允許(JSON)尾隨逗號;
  • 可定制轉換器;
  • 使用[JsonExtensionData]特性指示在反序列化時沒有匹配成員的屬性存放處(a property overflow bag);(注:當屬性的類型為IDictionary<TKey,TValue>時,沒有匹配成員的任何屬性都會在反序列化期間添加到該字典中,並在序列化期間中寫入)
  • 使用[JsonIgnore]特性忽略特定的屬性;
  • 使用[JsonProperty]特性來指定自定義屬性名。(注:未使用[JsonProperty]特性時Json對應的實體類屬性名需要與Json對應屬性完全一致,使用[JsonProperty]特性標識PropertyName后,實體類屬性名可自定義)

序列化選項設置

    1. 自定義單個屬性名稱
    2. 對所有 JSON 屬性名稱使用 camel 大小寫
    3. 使用[JsonPropertyName("Wind")]自定義 JSON 屬性命名策略
    4. JsonStringEnumConverter()將字典鍵Key的作為Json屬性的命名規則
    5. 枚舉做為Json屬性的命名規則
    6. 使用[JsonPropertyOrder(數值)]自定義序列化Json屬性的順序

【C# 序列化】序列化控制 JsonProperty 結構

序列化控制

內容來源:https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-configure-options?pivots=dotnet-6-0

Text.Json​​新增了4個接口

    IJsonOnDeserialized代替[OnSerialized]
    IJsonOnDeserializing代替[OnSerializing]
    IJsonOnSerialized代替[OnDeserialized]
    IJsonOnSerializing代替[OnDeserializing]

 IJsonOnDeserializing, IJsonOnDeserialized,  IJsonOnSerializing, IJsonOnSerialized
public class Serializeables : IJsonOnDeserializing, IJsonOnDeserialized,IJsonOnSerializing, IJsonOnSerialized
{

    public bool[] Serbool = { true, true, true };
    public void OnSerializing() => Console.WriteLine("序列化中");
    public void OnDeserializing() => Console.WriteLine("反序列化中");
    public void OnDeserialized() =>  Console.WriteLine("反序列化后");
    public void OnSerialized() => Console.WriteLine("序列化后");
  
}

[JsonIgnore] 特性 忽略屬性

“序列化通知”功能對於設置默認值和驗證屬性值合法性非常有用。​

 JsonIgnoreCondition Enum

Always  1  屬性將始終被忽略。
Never  0  屬性將始終被序列化和反序列化,無論IgnoreNullValues配置如何。無論 DefaultIgnoreConditionIgnoreReadOnlyPropertiesIgnoreReadOnlyFields 全局設置如何,始終序列化和反序列化屬性。
WhenWritingDefault  2  屬性只有在為空時才會被忽略。如果屬性是引用類型 null可為 null 的值類型 null 或值類型 default,則在序列化中忽略屬性。
WhenWritingNull  3     如果該值為空,則在序列化期間忽略該屬性。這只適用於引用類型的屬性和字段。WhenWritingNull - 如果屬性是引用類型 null 或可為 null 的值類型 null,則在序列化中忽略屬性。

public class MySerializeable
{
    [JsonIgnore(Condition =JsonIgnoreCondition.Always)]
    public   string Name = "dfdf";//被忽略

    [JsonIgnore(Condition =JsonIgnoreCondition.Never)]
    public string Name2 = "dfdf";

    [JsonIgnore(Condition =JsonIgnoreCondition.WhenWritingDefault)]
    public string Name3 = default;//將被忽略,因為使用默認值

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string Name4 =null;//會被忽略因為null

}

綜合使用案例

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using System.Text.Unicode;

JsonSerializerOptions jso = new JsonSerializerOptions
{
    WriteIndented = true,
    PropertyNameCaseInsensitive = true,
    DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    ReadCommentHandling = JsonCommentHandling.Skip, //跳過注釋
    AllowTrailingCommas = true,//忽略逗號
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,//屬性名的格式,駝峰
    NumberHandling = JsonNumberHandling.AllowReadingFromString,//反序列化的時候用的到
    IncludeFields=true,
    //保證中文字符正確顯示。CjkUnifiedIdeographs 象行文字 代表中文(Chinese)、日文(Japanese )、韓文(Korean)的字符集合
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.CjkUnifiedIdeographs),//從拉丁文字到象行文字
};


var json=JsonSerializer.SerializeToNode(new Myserliazer("祖海", "Summary", "Summary", "Summary"),jso);
Console.WriteLine(json.ToJsonString(options: jso));

public class Myserliazer 
{
    public Myserliazer()
    {
            
    }
    [JsonConstructor]
    public Myserliazer(string name, string sumary, string description, string keyword) =>
        (Name, Summary, Description, KeyWord) = (name, sumary, description, keyword);
   
    //[JsonInclude] 用法
    [JsonInclude]
    public string Name = "董卿";
    [JsonInclude]//若要允許使用非公共屬性訪問器,請使用 [JsonInclude] 特性
    public string? Summary { private get; set; } = "Summary";
    [JsonInclude]
    public string Content { get; private set; } = @"[OnSerialized()] internal void OnSerializedMethod(StreamingContext context) ... the call to the onSerializing method when the serialized objects are equal.";
    public string Frend = "哈哈";

    //[JsonIgnore]用法
    public string Description { get; set; } = "My first int";
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
    public string KeyWord { get; set; } = "Web Site";
    [JsonIgnore(Condition = JsonIgnoreCondition.Always)]
    public DateTime DateTimenow { get; set; } = DateTime.Now;

    public string Eeditor{ get; }

    // [JsonExtensionData]用法
    [JsonExtensionData]
    public Dictionary<string, JsonElement>? ExtensionData { get; set; } = new Dictionary<string, JsonElement>();
    
    // [JsonPropertyName]用法
    [JsonPropertyName("Cangpr0pety")]
    public string ChangPr0pety { set; get; } = "ChangPr0pety";
    public int Age { set; get; } = 12;
    public void OnDeserializing()
    {
        throw new NotImplementedException();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM