【C# 序列化】序列化選項 JsonSerializerOptions 類
內容來源:https://docs.microsoft.com/zh-cn/dotnet/api/system.text.json.jsonproperty?view=net-6.0
名稱空間System.Text.Json
JsonSerializerOptions 類
序列化選項用於控制要物件的序列化的或這Json 字元的反序列化,
建構函式
內容來源:如何使用 System.Text.Json 例項化 JsonSerializerOptions 例項
JsonSerializerOptions() :初始化JsonSerializerOptions類的一個新例項。
JsonSerializerOptions(JsonSerializerDefaults) :用由指定的JsonSerializerDefaults確定的預定義選項集構造一個新的
JsonSerializerOptions(JsonSerializerOptions) :將選項從JsonSerializerOptions例項複製到一個新例項。
建構函式的使用
1、重用JsonSerializerOptions例項
如果你使用相同的選項重複使用JsonSerializerOptions,不要每次使用時都建立一個新的JsonSerializerOptions例項。為每個呼叫重用相同的例項。此指導適用於為自定義轉換器編寫的程式碼和呼叫JsonSerializer時。序列化或JsonSerializer.Deserialize。跨多個執行緒使用相同的例項是安全的。選項例項上的元資料快取是執行緒安全的,並且該例項在第一次序列化或反序列化之後是不可變的。
下面的程式碼演示了使用新選項例項的效能損失。
JsonSerializerOptions(JsonSerializerDefaults)案例如下:
using System.Diagnostics; using System.Text.Json; namespace OptionsPerfDemo { public record Forecast(DateTime Date, int TemperatureC, string Summary); public class Program { public static void Main() { Forecast forecastView Code= new(DateTime.Now, 40, "Hot"); JsonSerializerOptions options = new() { WriteIndented = true }; int iterations = 100000; var watch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { Serialize(forecast, options); } watch.Stop(); Console.WriteLine($"Elapsed time using one options instance: {watch.ElapsedMilliseconds}"); watch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { Serialize(forecast); } watch.Stop(); Console.WriteLine($"Elapsed time creating new options instances: {watch.ElapsedMilliseconds}"); } private static void Serialize(Forecast forecast, JsonSerializerOptions? options = null) { _ = JsonSerializer.Serialize<Forecast>( forecast, options ?? new JsonSerializerOptions() { WriteIndented = true }); } } } // Produces output like the following example: // //Elapsed time using one options instance: 190 //Elapsed time creating new options instances: 40140
2、JsonSerializerOptions的Web預設值為JsonSerializerDefaults.Web
JsonSerializerDefaults.Web
列舉專案包含以下:
-
PropertyNameCaseInsensitive =
true
- JsonNamingPolicy = CamelCase
- NumberHandling = AllowReadingFromString
有一個JsonSerializerOptions建構函式,它允許您用ASP的預設選項建立一個新例項。NET Core用於web應用程式,如下例所示:
using System.Text.Json; namespace OptionsDefaults { public class Forecast { public DateTime? Date { get; init; } public int TemperatureC { get; set; } public string? Summary { get; set; } }; public class Program { public static void Main() { Forecast forecast = new() { Date = DateTime.Now, TemperatureC = 40, Summary = "Hot" }; JsonSerializerOptions options = new(JsonSerializerDefaults.Web) { WriteIndented = true }; Console.WriteLine( $"PropertyNameCaseInsensitive: {options.PropertyNameCaseInsensitive}"); Console.WriteLine( $"JsonNamingPolicy: {options.PropertyNamingPolicy}"); Console.WriteLine( $"NumberHandling: {options.NumberHandling}"); string forecastJson = JsonSerializer.Serialize<Forecast>(forecast, options); Console.WriteLine($"Output JSON:\n{forecastJson}"); Forecast? forecastDeserialized = JsonSerializer.Deserialize<Forecast>(forecastJson, options); Console.WriteLine($"Date: {forecastDeserialized?.Date}"); Console.WriteLine($"TemperatureC: {forecastDeserialized?.TemperatureC}"); Console.WriteLine($"Summary: {forecastDeserialized?.Summary}"); } } } // Produces output like the following example: // //PropertyNameCaseInsensitive: True //JsonNamingPolicy: System.Text.Json.JsonCamelCaseNamingPolicy //NumberHandling: AllowReadingFromString //Output JSON: //{ // "date": "2020-10-21T15:40:06.9040831-07:00", // "temperatureC": 40, // "summary": "Hot" //} //Date: 10 / 21 / 2020 3:40:06 PM //TemperatureC: 40 //Summary: HotView Code
3、複製JsonSerializerOptions
JsonSerializerOptions(JsonSerializerOptions) :將選項從JsonSerializerOptions例項複製到一個新例項。案例如下:
using System.Text.Json; namespace CopyOptions { public class Forecast { public DateTime Date { get; init; } public int TemperatureC { get; set; } public string? Summary { get; set; } }; public class Program { public static void Main() { Forecast forecast = new() { Date = DateTime.Now, TemperatureC = 40, Summary = "Hot" }; JsonSerializerOptions options = new() { WriteIndented = true }; JsonSerializerOptions optionsCopy = new(options); string forecastJson = JsonSerializer.Serialize<Forecast>(forecast, optionsCopy); Console.WriteLine($"Output JSON:\n{forecastJson}"); } } } // Produces output like the following example: // //Output JSON: //{ // "Date": "2020-10-21T15:40:06.8998502-07:00", // "TemperatureC": 40, // "Summary": "Hot" //}View Code
屬性:
記憶方法:4個Hand(列舉處理、陣列處理) 、3個Ignore、Json屬性命名策略 3(屬性名命名規則、字典key做Json屬性命名規則、師傅) 其他。
- AllowTrailingCommas 允許尾部的逗號 獲取或設定一個值,該值指示在被反序列化的JSON有效負載中,是否允許(或忽略)在物件或陣列中的JSON值列表的末尾新增額外的逗號。
- Converters 變換器 獲取已註冊的使用者定義轉換器的列表。
- DefaultBufferSize 預設緩衝區大小 獲取或設定建立臨時緩衝區時要使用的預設緩衝區大小(以位元組為單位)。
- DefaultIgnoreCondition 忽略所有預設值屬性 獲取或設定一個值,該值確定在序列化或反序列化期間何時忽略具有預設值的屬性。預設值為“Never”。用到JsonIgnoreCondition列舉
- DictionaryKeyPolicy 字典Key的命名規則 獲取或設定用於將IDictionary鍵名轉換為另一種格式(如駝色大小寫)的策略。
- Encoder 編碼器 獲取或設定轉義字串時要使用的編碼器,或為空以使用預設編碼器。https://www.cnblogs.com/cdaniu/p/16024229.html
- IgnoreNullValues 忽略 NullValues 過時了。獲取或設定一個值,該值指示在序列化和反序列化期間是否忽略空值。預設值為false。
- IgnoreReadOnlyFields 忽略只讀欄位 獲取或設定一個值,該值指示在序列化期間是否忽略只讀欄位。如果一個欄位被標記為readonly關鍵字,那麼它就是隻讀的。預設值為false。
- IgnoreReadOnlyProperties 忽略只讀取屬性 獲取一個值,該值指示在序列化期間是否忽略只讀屬性。預設值為false。
- IncludeFields 是否序列化欄位 獲取或設定一個值,該值指示是否在序列化和反序列化期間處理欄位。預設值為false, 設定位true後,就可以序列化屬性和欄位。。
- MaxDepth 最大深度 獲取或設定序列化或反序列化JSON時允許的最大深度,預設值0表示最大深度為64。一個物件(或陣列)A{}的深度為0,物件(或陣列)中巢狀物件或陣列A{B[]} 深度為1 以此類推
- NumberHandling 數字的序列化/反序列化方式 獲取或設定一個物件,該物件指定在序列化或反序列化時應如何處理數字型別,此屬性是在序列化或反序列化發生後設置的。用到JsonNumberHandling 位列舉
- PropertyNameCaseInsensitive 反序列化期間屬性名稱大小寫不區分 獲取或設定一個值,該值指示屬性的名稱在反序列化期間是否使用不區分大小寫的比較。預設值為false 區分大小寫。用到JsonSerializerDefaults 列舉
- PropertyNamingPolicy 命名規則 獲取或設定一個值,該值指定用於將物件上的屬性名稱轉換為另一種格式(例如駝峰大小寫)或為空以保持屬性名稱不變的策略。
-
ReadCommentHandling 閱讀註釋處理 獲取或設定一個值,該值定義在反序列化期間如何處理註釋, 用到
JsonCommentHandling列舉
。 - ReferenceHandler 引用處理程式 獲取或設定一個物件,該物件指定在讀取和寫入JSON時如何處理物件引用 用到 ReferenceHandler 類。
- UnknownTypeHandling 未知型別處理 獲取或設定一個物件,該物件指定在反序列化期間如何處理宣告為object的型別的反序列化。
- WriteIndented 按格式輸出 獲取或設定一個值,該值指示JSON是否應該使用格式化列印。預設情況下false,JSON序列化時沒有任何額外的空格。
2、Converters :【C# 序列化】 自定義Json轉換器模式
詳細請檢視:https://www.cnblogs.com/cdaniu/p/15968261.html
4、忽略所有預設值屬性/或欄位
設定該屬性,需要JsonIgnoreCondition列舉。若要防止對值型別屬性中的預設值進行序列化,請將 DefaultIgnoreCondition 屬性設定為JsonIgnoreCondition.WhenWritingDefault,如以下示例中所示:
相當於
[JsonIgnore(Condition =JsonIgnoreCondition.WhenWritingDefault)] public string Name3 = default;//將被忽略,因為使用預設值
MySerializeable serializeable = new (); var serializeOption = new JsonSerializerOptions() { AllowTrailingCommas=false, WriteIndented=true, DefaultIgnoreCondition=JsonIgnoreCondition.WhenWritingDefault,//忽略預設的屬性或欄位 IncludeFields=true,//開啟忽略欄位,預設情況下是false }; string jsonString = JsonSerializer.Serialize(serializeable,serializeOption); writer.WriteLine(jsonString); writer.Close(); public class MySerializeable { public int Name4 ;//會被忽略因為是預設值 }
5、字典Key序列化的命名規則
如果要序列化的物件的屬性為 Dictionary<string,TValue>
型別,則 string
鍵可轉換為 camel 大小寫。 為此,請將 DictionaryKeyPolicy 設定為 JsonNamingPolicy.CamelCase
,如下面的示例中所示:
MySerializeable serializeable = new() ; serializeable.Lictionaryy.Add("XiaoMi","26"); serializeable.Lictionaryy.Add("LuaWei", "26"); var serializeOption = new JsonSerializerOptions() { WriteIndented = true, DictionaryKeyPolicy =JsonNamingPolicy.CamelCase, }; string jsonString = JsonSerializer.Serialize<MySerializeable>(serializeable,serializeOption); var desr=JsonSerializer.Deserialize<MySerializeable>(jsonString,serializeOption);//反序列化時候要使用序列化配置 Console.WriteLine(jsonString); Console.Read(); public class MySerializeable { public double FloatNumberOne { get; set; } public int NumberTwo { get; set; } public Dictionary<string,string> Lictionaryy { get; set; }=new Dictionary<string,string>(); } /*{ "FloatNumberOne": "NaN", "NumberTwo": 123, "Lictionaryy": { "xiaoMi": "26", "luaWei": "26" } }*/
6、Encoder
//保證中文字元正確顯示。CjkUnifiedIdeographs 象行文字 代表中文(Chinese)、日文(Japanese )、韓文(Korean)的字元集合 JsonSerializerOptions jso = new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.CjkUnifiedIdeographs),//從拉丁文字到象行文字 }; public class Myserliazer { [JsonInclude] public string Name = "哈哈" }
8條和9條 IgnoreReadOnlyFields和IgnoreReadOnlyProperties
忽略大小
StreamWriter writer = GetCurrentStream(); MySerializeable serializeable = new (); var serializeOption = new JsonSerializerOptions() { AllowTrailingCommas=false, WriteIndented=true, IgnoreReadOnlyFields=true, //忽略只讀欄位 IgnoreReadOnlyProperties=false, //預設false }; string jsonString = JsonSerializer.Serialize(serializeable,serializeOption); writer.WriteLine(jsonString); writer.Close(); StreamWriter GetCurrentStream() { Environment.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); string fullName = Directory.CreateDirectory("Test").FullName; StreamWriter streamWriter = File.CreateText(Path.Combine(fullName, "text.txt")); return streamWriter; } public class MySerializeable { public readonly string Name = "dfdf"; public readonly int[] Info= { 10, 20, 30 }; public string Description { private set; get; } } /*輸出 * { "Description": null, "Info": [ 10, 20, 30 ] }*/
10條和18條IncludeFields和WriteIndented
StreamWriter writer = GetCurrentStream(); MySerializeable serializeable = new (); var serializeOption = new JsonSerializerOptions() { AllowTrailingCommas=false, IncludeFields = true,//包含欄位,預設只包含屬性,設定位true後,就可以序列化屬性和欄位。 WriteIndented=true,//格式化輸出 }; string jsonString = JsonSerializer.Serialize(serializeable,serializeOption); writer.WriteLine(jsonString); writer.Close(); StreamWriter GetCurrentStream() { Environment.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); string fullName = Directory.CreateDirectory("Test").FullName; StreamWriter streamWriter = File.CreateText(Path.Combine(fullName, "text.txt")); return streamWriter; } public class MySerializeable { public string Name = "dfdf"; public int[] Info= { 10, 20, 30 }; } /*輸出 * { "Name": "dfdf", "Info": [ 10, 20, 30 ] }*/
11、MaxDepth
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using GongHuiNewtonsoft.Json; using GongHuiNewtonsoft.Json.Serialization; using GongHuiNewtonsoft.Json.Converters; namespace JSONDemo { class Program { static void Main(string[] args) { try { JsonConvert.DeserializeObject<List<IList<IList<string>>>>(@"[ [ [ '3', 'Three', 'III' ] ] ]", new JsonSerializerSettings { MaxDepth = 2 //MaxDepth=3 }); } catch (JsonReaderException ex) { Console.WriteLine(ex.Message); } } } }
12、序列化/反序列化數字解析方式
在設定JsonNumberHandling選項時用到JsonSerializerDefaults 位列舉
序列化和反序列化時數字的儲存和解析方法
【AllowNamedFloatingPointLiterals 模式】不是標準的json格式,“NaN”、“Infinity”和“-Infinity”字串標記可以被讀為浮點常量,這些常量的Single和Double值將被寫為它們對應的JSON字串表示。
【Strict 反序列化模式】數字將只從數字標記讀取,將只被寫入JSON數字("Number":123,)。
【AllowReadingFromString 反序列化模式】可以從String令牌中讀取數字。不阻止從Number令牌讀取數字。Number":"123"
【WriteAsString 序列化模式】不是標準的json格式,序列化時將數字寫成字串的形式。
使用案例:
MySerializeable serializeable = new() ; serializeable.FloatNumberOne = double.NaN;//序列化時候,需要將 NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,否會出錯 serializeable.NumberTwo = 123; var serializeOption = new JsonSerializerOptions() { WriteIndented = true, NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals| JsonNumberHandling.AllowReadingFromString| JsonNumberHandling.WriteAsString, }; string jsonString = JsonSerializer.Serialize<MySerializeable>(serializeable,serializeOption); var desr=JsonSerializer.Deserialize<MySerializeable>(jsonString,serializeOption);//反序列化時候要使用序列化配置,不配置會報錯 Console.WriteLine(jsonString); public class MySerializeable { public double FloatNumberOne { get; set; } public int NumberTwo { get; set; } }
13、反序列化時不區分屬性大小寫
預設情況下,反序列化會查詢 JSON 與目標物件屬性之間區分大小寫的屬性名稱匹配。 若要更改該行為,請將 JsonSerializerOptions.PropertyNameCaseInsensitive 設定為 true
:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options); public class WeatherForecast { public DateTimeOffset Date { get; set; } public int TemperatureCelsius { get; set; } public string? Summary { get; set; } } /*{ "date": "2019-08-01T00:00:00-07:00", "temperatureCelsius": 25, "summary": "Hot", } */
14、PropertyNamingPolicy 命名規則
該選項用到JsonNamingPolicy 類,可以繼承該類重寫ConvertName()方法自定義命名規則
MySerializeable serializeable = new() ; serializeable.FloatNumberOne = double.NaN;//序列化時候,需要將 NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals serializeable.NumberTwo = 123; var serializeOption = new JsonSerializerOptions() { WriteIndented = true, NumberHandling=JsonNumberHandling.AllowNamedFloatingPointLiterals, PropertyNamingPolicy =JsonNamingPolicy.CamelCase, }; string jsonString = JsonSerializer.Serialize<MySerializeable>(serializeable,serializeOption); var desr=JsonSerializer.Deserialize<MySerializeable>(jsonString,serializeOption);//反序列化時候要使用序列化配置 Console.WriteLine(jsonString); Console.Read(); public class MySerializeable { public double FloatNumberOne { get; set; } public int NumberTwo { get; set; } } /*{ "floatNumberOne": "NaN", "numberTwo": 123 }*/
自定義命名規則。
MySerializeable serializeable = new() ; serializeable.FloatNumberOne = double.NaN;//序列化時候,需要將 NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals serializeable.NumberTwo = 123; var serializeOption = new JsonSerializerOptions() { WriteIndented = true, NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, PropertyNamingPolicy = new ToUpper(), }; string jsonString = JsonSerializer.Serialize<MySerializeable>(serializeable,serializeOption); var desr=JsonSerializer.Deserialize<MySerializeable>(jsonString,serializeOption);//反序列化時候要使用序列化配置 Console.WriteLine(jsonString); Console.Read(); public class ToUpper : JsonNamingPolicy { public override string ConvertName(string name) => name.ToUpper(); } public class MySerializeable { public double FloatNumberOne { get; set; } public int NumberTwo { get; set; } } /*{ "FLOATNUMBERONE": "NaN", "NUMBERTWO": 123 }*/View Code
15、允許註釋
預設情況下,JSON 中不允許使用註釋和尾隨逗號。 若要在 JSON 中允許註釋,請將 JsonSerializerOptions.ReadCommentHandling 屬性設定為 JsonCommentHandling.Skip
。
var options = new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, }; var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options)!;
下面是包含註釋和尾隨逗號的示例 JSON:
{ "Date": "2019-08-01T00:00:00-07:00", "TemperatureCelsius": 25, // Fahrenheit 77 "Summary": "Hot", /* Zharko */ // Comments on /* separate lines */ }
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("序列化後"); }
特性