【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) :將選項從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 forecast = 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
View Code

 

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: Hot
View 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屬性命名規則、師傅) 其他。

  1. AllowTrailingCommas     允許尾部的逗號    獲取或設置一個值,該值指示在被反序列化的JSON有效負載中,是否允許(或忽略)在對象或數組中的JSON值列表的末尾添加額外的逗號。
  2. Converters     變換器    獲取已注冊的用戶定義轉換器的列表。
  3. DefaultBufferSize     默認緩沖區大小    獲取或設置創建臨時緩沖區時要使用的默認緩沖區大小(以字節為單位)。
  4. DefaultIgnoreCondition     忽略所有默認值屬性   獲取或設置一個值,該值確定在序列化或反序列化期間何時忽略具有默認值的屬性。缺省值為“Never”。用到JsonIgnoreCondition枚舉
  5. DictionaryKeyPolicy     字典Key的命名規則    獲取或設置用於將IDictionary鍵名轉換為另一種格式(如駝色大小寫)的策略。
  6. Encoder     編碼器    獲取或設置轉義字符串時要使用的編碼器,或為空以使用默認編碼器。https://www.cnblogs.com/cdaniu/p/16024229.html
  7. IgnoreNullValues     忽略 NullValues    過時了。獲取或設置一個值,該值指示在序列化和反序列化期間是否忽略空值。缺省值為false。
  8. IgnoreReadOnlyFields     忽略只讀字段    獲取或設置一個值,該值指示在序列化期間是否忽略只讀字段。如果一個字段被標記為readonly關鍵字,那么它就是只讀的。缺省值為false。
  9. IgnoreReadOnlyProperties     忽略只讀取屬性    獲取一個值,該值指示在序列化期間是否忽略只讀屬性。缺省值為false。
  10. IncludeFields     是否序列化字段    獲取或設置一個值,該值指示是否在序列化和反序列化期間處理字段。缺省值為false,  設置位true后,就可以序列化屬性和字段。
  11. MaxDepth     最大深度    獲取或設置序列化或反序列化JSON時允許的最大深度,默認值0表示最大深度為64。一個對象(或數組)A{}的深度為0,對象(或數組)中嵌套對象或數組A{B[]} 深度為1 以此類推
  12. NumberHandling     數字的序列化/反序列化方式    獲取或設置一個對象,該對象指定在序列化或反序列化時應如何處理數字類型,此屬性是在序列化或反序列化發生后設置的。用到JsonNumberHandling 位枚舉
  13. PropertyNameCaseInsensitive     反序列化期間屬性名稱大小寫不區分    獲取或設置一個值,該值指示屬性的名稱在反序列化期間是否使用不區分大小寫的比較。缺省值為false 區分大小寫。用到JsonSerializerDefaults 枚舉
  14. PropertyNamingPolicy     命名規則    獲取或設置一個值,該值指定用於將對象上的屬性名稱轉換為另一種格式(例如駝峰大小寫)或為空以保持屬性名稱不變的策略。
  15. ReadCommentHandling     閱讀注釋處理    獲取或設置一個值,該值定義在反序列化期間如何處理注釋, 用到JsonCommentHandling枚舉
  16. ReferenceHandler     引用處理程序    獲取或設置一個對象,該對象指定在讀取和寫入JSON時如何處理對象引用  用到 ReferenceHandler 類。
  17. UnknownTypeHandling     未知類型處理    獲取或設置一個對象,該對象指定在反序列化期間如何處理聲明為object的類型的反序列化。
  18. 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("序列化后");
  
}

 

特性

 


免責聲明!

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



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