命名空间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)案例如下:

ios JSONSerialization 顺序 jsonserializeroptions_JSON

ios JSONSerialization 顺序 jsonserializeroptions_JSON_02

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应用程序,如下例所示:

ios JSONSerialization 顺序 jsonserializeroptions_JSON

ios JSONSerialization 顺序 jsonserializeroptions_JSON_02

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实例复制到一个新实例。案例如下:

 

ios JSONSerialization 顺序 jsonserializeroptions_JSON

ios JSONSerialization 顺序 jsonserializeroptions_JSON_02

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
  2. Converters
  3. DefaultBufferSize     默认缓冲区大小    获取或设置创建临时缓冲区时要使用的默认缓冲区大小(以字节为单位)。
  4. DefaultIgnoreCondition
  5. DictionaryKeyPolicy
  6. Encoder     编码器    获取或设置转义字符串时要使用的编码器,或为空以使用默认编码器。
  7. IgnoreNullValues     忽略 NullValues    过时了。获取或设置一个值,该值指示在序列化和反序列化期间是否忽略空值。缺省值为false。
  8. IgnoreReadOnlyFields
  9. IgnoreReadOnlyProperties
  10. IncludeFields     是否序列化字段    获取或设置一个值,该值指示是否在序列化和反序列化期间处理字段。缺省值为false,  设置位true后,就可以序列化属性和字段。。
  11. MaxDepth
  12. NumberHandling
  13. PropertyNameCaseInsensitive
  14. PropertyNamingPolicy  
  15. ReadCommentHandling     阅读注释处理    获取或设置一个值,该值定义在反序列化期间如何处理注释, 用到JsonCommentHandling枚举
  16. ReferenceHandler
  17. UnknownTypeHandling     未知类型处理    获取或设置一个对象,该对象指定在反序列化期间如何处理声明为object的类型的反序列化。
  18. WriteIndented

2、Converters   :【C# 序列化】 自定义Json转换器模式

详细请查看:

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
}*/

 自定义命名规则。

ios JSONSerialization 顺序 jsonserializeroptions_JSON

ios JSONSerialization 顺序 jsonserializeroptions_JSON_02

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("序列化后");
  
}

 

特性

 

编程是个人爱好