Asp .Net Core 系列:Asp .Net Core 配置 System.Text.Json

文章目录

    • 简介
    • Asp .Net Core 如何配置 System.Text.Json
      • 所有配置
      • 全局配置
    • 对比 Newtonsoft.Json
    • 无实体类型下操作 Json
    • 自定义转换器
    • 处理 Dynamic 类型
    • 封装常用配置
    • 封装 JsonHelper 帮助类

简介

System.Text.Json 命名空间提供用于序列化和反序列化 JavaScript 对象表示法 (JSON) 的功能。 序列化是将对象状态(即其属性的值)转换为可存储或传输的形式的过程。 序列化形式不包含有关对象的关联方法的任何信息。 反序列化从序列化形式重新构造对象。

System.Text.Json 库的设计强调对广泛的功能集实现高性能和低内存分配。 内置的 UTF-8 支持可优化读写以 UTF-8 编码的 JSON 文本的过程,UTF-8 编码是针对 Web 上的数据和磁盘上的文件的最普遍的编码方式。

库还提供了用于处理内存中文档对象模型 (DOM) 的类。 此功能允许对 JSON 文件或字符串中的元素进行随机访问。

该库是作为 .NET Core 3.0 及更高版本共享框架的一部分内置的。 源生成功能内置在 .NET 6 和更高版本的共享框架中。

对于早于 .NET Core 3.0 的框架版本,请安装 System.Text.Json NuGet 包。 包支持以下框架:

  • .NET Standard 2.0 及更高版本
  • .NET Framework 4.6.2 及更高版本
  • .NET Core 2.1 及更高版本
  • .NET 5 及更高版本

https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json/overview

Asp .Net Core 如何配置 System.Text.Json

所有配置

https://learn.microsoft.com/zh-cn/dotnet/api/system.text.json.jsonserializeroptions?view=net-8.0&source=recommendations

AllowTrailingCommas获取或设置一个值,该值指示要反序列化的 JSON 有效负载中是否允许(和忽略)对象或数组中 JSON 值的列表末尾多余的逗号。
Converters获取已注册的用户定义的转换器的列表。
Default获取使用默认配置的 的 JsonSerializerOptions 只读单一实例。
DefaultBufferSize获取或设置创建临时缓冲区时要使用的默认缓冲区大小(以字节为单位)。
DefaultIgnoreCondition获取或设置一个值,该值确定在序列化或反序列化期间何时忽略具有默认值的属性。 默认值为 Never。
DictionaryKeyPolicy获取或设置用于将 IDictionary 密钥名称转换为其他格式(如 camel 大小写)的策略。
Encoder获取或设置要在转义字符串时使用的编码器,或为 null(要使用默认编码器的话)。
IgnoreNullValues**已过时。**获取或设置一个值,该值指示在序列化和反序列化期间是否 null 忽略值。 默认值为 false
IgnoreReadOnlyFields获取或设置一个值,该值指示在序列化期间是否忽略只读字段。 如果某字段用 readonly 关键字进行标记,则该字段为只读字段。 默认值为 false
IgnoreReadOnlyProperties获取一个值,该值指示在序列化期间是否忽略只读属性。 默认值为 false
IncludeFields获取或设置一个值,该值指示是否在序列化和反序列化期间处理字段。 默认值为 false
IsReadOnly获取一个值,该值指示当前实例是否已锁定以供用户修改。
MaxDepth获取或设置序列化或反序列化 JSON 时允许的最大深度,默认值 0 表示最大深度为 64。
NumberHandling获取或设置一个 对象,该对象指定序列化或反序列化时应如何处理数字类型。
PreferredObjectCreationHandling获取或设置反序列化 JSON 时属性的首选对象创建处理。
PropertyNameCaseInsensitive获取或设置一个值,该值指示属性名称在反序列化期间是否使用不区分大小写的比较。 默认值为 false
PropertyNamingPolicy获取或设置一个值,该值指定用于将对象的属性名称转换为其他格式(例如 camel 大小写)的策略;若为 null,则保持属性名称不变。
ReadCommentHandling获取或设置一个值,该值定义反序列化过程中如何处理注释。
ReferenceHandler获取或设置一个 对象,该对象指定在读取和写入 JSON 时如何处理对象引用。
TypeInfoResolver获取或设置 JsonTypeInfo 此实例使用的协定解析程序。
TypeInfoResolverChain获取此实例使用的已 JsonTypeInfo 链接协定解析程序的列表。
UnknownTypeHandling获取或设置一个 对象,该对象指定如何在反序列化过程中反序列化声明为 Object 的类型。
UnmappedMemberHandling获取或设置一个 对象,该对象指定在反序列化对象类型时如何处理 JsonSerializer 无法映射到特定 .NET 成员的 JSON 属性。
WriteIndented获取或设置一个值,该值指示 JSON 是否应使用美观打印。 默认情况下,不使用任何额外的空白来序列化 JSON。

全局配置

AddControllers() 后面添加 AddJsonOptions 方法

   builder.Services.AddControllers().AddJsonOptions(options=> {options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;});

对比 Newtonsoft.Json

https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json/migrate-from-newtonsoft?pivots=dotnet-8-0#table-of-differences

Newtonsoft.Json 功能System.Text.Json 等效
默认情况下不区分大小写的反序列化✔️ PropertyNameCaseInsensitive 全局设置
Camel 大小写属性名称✔️ PropertyNamingPolicy 全局设置
对属性名称采用蛇形命名法✔️ 蛇形命名法命名策略
最小字符转义✔️ 严格字符转义,可配置
NullValueHandling.Ignore 全局设置✔️ DefaultIgnoreCondition 全局选项
允许注释✔️ ReadCommentHandling 全局设置
允许尾随逗号✔️ AllowTrailingCommas 全局设置
自定义转换器注册✔️ 优先级顺序不同
默认情况下无最大深度✔️ 默认最大深度为 64,可配置
PreserveReferencesHandling 全局设置✔️ ReferenceHandling 全局设置
序列化或反序列化带引号的数字✔️ [NumberHandling 全局设置,JsonNumberHandling] 特性
反序列化为不可变类和结构✔️ JsonConstructor,C# 9 记录
支持字段✔️ [IncludeFields 全局设置,JsonInclude] 特性
DefaultValueHandling 全局设置✔️ DefaultIgnoreCondition 全局设置
[JsonProperty] 上的 NullValueHandling 设置✔️ JsonIgnore 特性
[JsonProperty] 上的 DefaultValueHandling 设置✔️ JsonIgnore 特性
反序列化具有非字符串键的 Dictionary✔️ 受支持
支持非公共属性资源库和 Getter✔️ JsonInclude 特性
[JsonConstructor] 特性✔️ [JsonConstructor] 特性
ReferenceLoopHandling 全局设置✔️ ReferenceHandling 全局设置
回调✔️ 回调
NaN、Infinity、-Infinity✔️ 受支持
[JsonProperty] 特性上的 Required 设置✔️ [JsonRequired] 特性和 C# 必需的修饰符
DefaultContractResolver 用于忽略属性✔️ DefaultJsonTypeInfoResolver 类
多态序列化✔️ [JsonDerivedType] 特性
多态反序列化✔️ [JsonDerivedType] 特性上的类型鉴别器
反序列化字符串枚举值✔️ 反序列化字符串枚举值
MissingMemberHandling 全局设置✔️ 处理缺少的成员
在没有资源库的情况下填充属性✔️ 在没有资源库的情况下填充属性
ObjectCreationHandling 全局设置✔️ 重用而不是替换属性
支持范围广泛的类型⚠️ ⚠
将推断类型反序列化为 object 属性⚠️ ⚠
将 JSON null 文本反序列化为不可为 null 的值类型⚠️ ⚠
DateTimeZoneHandlingDateFormatString 设置⚠️ ⚠
JsonConvert.PopulateObject 方法⚠️ ⚠
支持 System.Runtime.Serialization 特性⚠️ ⚠
JsonObjectAttribute⚠️ ⚠
允许不带引号的属性名称❌设计上不受支持
字符串值前后允许单引号❌设计上不受支持
对字符串属性允许非字符串 JSON 值❌设计上不受支持
TypeNameHandling.All 全局设置❌设计上不受支持
支持 JsonPath 查询❌不支持
可配置的限制❌不支持

无实体类型下操作 Json

类似 Newtonsoft.Json,在没有实体类的情况下,也可以使用 JsonNode/JsonValue/JsonArray/JsonObject 操作 json。

image

自定义转换器

  • DateTimeConverter - DateTime 类型转换器
  • DateOnlyConverter - DateOnly 类型转换器
  • TimeOnlyConverter - TimeOnly 类型转换器
  • LongConverter - Long 类型转换器
  • Int32Converter - Int 类型转换器
  • DecimalConverter - Decimal 类型转换器
  • StringConverter - String 类型转换器
  • BooleanConverter - Boolean 类型转换器
  • NullAbleConverter - 可空类型转换器
  • EnumConverter - 枚举类型转换器
 public class JsonConverterExtensions{/// <summary>/// DateTime类型转换器/// </summary>public sealed class DateTimeConverter : JsonConverter<DateTime>{/// <summary>/// 格式化/// </summary>public string Format { get; set; } = "yyyy-MM-dd HH:mm:ss";/// <summary>/// 使用默认格式,同: <c>System.Text.Json.JsonSerializer.Serialize(obj)</c>/// </summary>public DateTimeConverter() { }/// <summary>/// 指定格式化字符串/// </summary>public DateTimeConverter(string format){Format = format;}public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.Null)return default;if (string.IsNullOrEmpty(reader.GetString())){return default;}else{return DateTime.TryParse(reader.GetString(), out DateTime result) ? result : default;}}public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options){writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));}}/// <summary>/// DateOnly类型转换器/// </summary>public sealed class DateOnlyConverter : JsonConverter<DateOnly>{/// <summary>/// 格式化/// </summary>public string Format { get; set; } = "yyyy-MM-dd";/// <summary>/// 使用默认格式,同: <c>System.Text.Json.JsonSerializer.Serialize(obj)</c>/// </summary>public DateOnlyConverter() { }/// <summary>/// 指定格式化字符串/// </summary>public DateOnlyConverter(string format){Format = format;}public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.Null)return default;if (string.IsNullOrEmpty(reader.GetString())){return default;}else{return DateOnly.TryParse(reader.GetString(), out DateOnly result) ? result : default;}}public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options){writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));}}/// <summary>/// TimeOnly类型转换器/// </summary>public sealed class TimeOnlyConverter : JsonConverter<TimeOnly>{/// <summary>/// 格式化/// </summary>public string Format { get; set; } = "HH:mm:ss";/// <summary>/// 使用默认格式,同: <c>System.Text.Json.JsonSerializer.Serialize(obj)</c>/// </summary>public TimeOnlyConverter() { }/// <summary>/// 指定格式化字符串/// </summary>public TimeOnlyConverter(string format){Format = format;}public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.Null)return default;if (string.IsNullOrEmpty(reader.GetString())){return default;}else{return TimeOnly.TryParse(reader.GetString(), out TimeOnly result) ? result : default;}}public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options){writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));}}/// <summary>/// Long类型转换器/// </summary>public sealed class LongConverter : JsonConverter<long>{public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.Null)return default;if (reader.TokenType == JsonTokenType.String){ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;if (Utf8Parser.TryParse(span, out long number, out int bytesConsumed) && span.Length == bytesConsumed)return number;if (long.TryParse(reader.GetString(), out number))return number;}return reader.GetInt64();}/// <summary>/// 注意这里在写入的时候转成了字符串/// </summary>/// <param name="writer"></param>/// <param name="value"></param>/// <param name="options"></param>public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options){writer.WriteStringValue(Convert.ToString(value));}}/// <summary>/// Int类型转换器/// </summary>public sealed class Int32Converter : JsonConverter<int>{public override int Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.Null)return default;if (reader.TokenType == JsonTokenType.String){ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed)return number;if (int.TryParse(reader.GetString(), out number))return number;}return reader.GetInt32();}public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options){writer.WriteNumberValue(value);}}/// <summary>/// Decimal类型转换器/// </summary>public sealed class DecimalConverter : JsonConverter<decimal>{public override decimal Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options){if (reader.TokenType == JsonTokenType.String){ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;if (Utf8Parser.TryParse(span, out decimal number, out int bytesConsumed) && span.Length == bytesConsumed)return number;if (decimal.TryParse(reader.GetString(), out number))return number;}if (reader.TokenType == JsonTokenType.Null)return default;return reader.GetDecimal();}public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options){writer.WriteNumberValue(value);}}/// <summary>/// String类型转换器/// </summary>public sealed class StringConverter : JsonConverter<string>{public override string Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options){switch (reader.TokenType){case JsonTokenType.None:case JsonTokenType.Null:return null;case JsonTokenType.Number:return reader.GetDouble().ToString();case JsonTokenType.True:return "true";case JsonTokenType.False:return "false";default:return reader.GetString();}return reader.GetString();}public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options){writer.WriteStringValue(value);}}/// <summary>/// Boolean类型转换器/// </summary>public sealed class BooleanConverter : JsonConverter<bool>{public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){switch (reader.TokenType){case JsonTokenType.None:case JsonTokenType.Null:throw new Exception($"无法将 null 反序列化为 bool!");case JsonTokenType.Number:var d = reader.GetDouble();return !(d == 0);case JsonTokenType.String:var str = reader.GetString();if (string.Equals(str, "true", StringComparison.OrdinalIgnoreCase)) return true;else if (string.Equals(str, "false", StringComparison.OrdinalIgnoreCase)) return false;else throw new Exception($"无法将非 \"true\"或\"false\" 的字符串 转为 bool!");case JsonTokenType.True: return true;case JsonTokenType.False: return false;default: throw new Exception($"无法将 {reader.TokenType} 反序列化为 bool!");}}public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options){writer.WriteBooleanValue(value);}}/// <summary>/// 可空类型转换器/// </summary>public sealed class NullAbleConverter : JsonConverterFactory{/// <summary>/// 是否是Nullable类型的/// </summary>/// <param name="type"></param>private static bool IsNullable(Type type){if (type == null) return false;return type.Name == "Nullable`1";}private static ConcurrentDictionary<Type, JsonConverter> _cache = new ConcurrentDictionary<Type, JsonConverter>();public override bool CanConvert(Type typeToConvert){return IsNullable(typeToConvert);}public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options){return _cache.GetOrAdd(typeToConvert, (c) =>{return (JsonConverter)Activator.CreateInstance(typeof(NullAbleConverter<>).MakeGenericType(typeToConvert));});}}/// <summary>/// 泛型可空类型转换器/// </summary>/// <typeparam name="T"></typeparam>public sealed class NullAbleConverter<T> : JsonConverter<T>{/// <summary>/// 是否是Nullable类型的/// </summary>/// <param name="type"></param>private static bool IsNullable(Type type){if (type == null) return false;return type.Name == "Nullable`1";}public NullAbleConverter(){s_UnderlyingType = Nullable.GetUnderlyingType(typeof(T));}private Type s_UnderlyingType = null;public override bool CanConvert(Type typeToConvert){return IsNullable(typeToConvert);}public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){switch (reader.TokenType){case JsonTokenType.Null:case JsonTokenType.None:return default;case JsonTokenType.String:var str = reader.GetString();if (str == string.Empty) return default;return (T)JsonSerializer.Deserialize(ref reader, s_UnderlyingType, options);default:return (T)JsonSerializer.Deserialize(ref reader, s_UnderlyingType, options);}}public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options){if (value == null){writer.WriteStringValue("null");}else{JsonSerializer.Serialize(writer, value, value.GetType(), options);}}}/// <summary>/// 枚举类型转换器/// </summary>public sealed class EnumConverter : JsonConverterFactory{public EnumConverter(bool enum2String = true){this.enum2String = enum2String;}private static ConcurrentDictionary<Type, JsonConverter> _cache2String = new ConcurrentDictionary<Type, JsonConverter>();private static ConcurrentDictionary<Type, JsonConverter> _cache2Numer = new ConcurrentDictionary<Type, JsonConverter>();private readonly bool enum2String;public sealed override bool CanConvert(Type typeToConvert){return typeToConvert.IsEnum;}public sealed override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options){var _cache = enum2String ? _cache2String : _cache2Numer;return _cache.GetOrAdd(typeToConvert, (c) =>{var ctor = typeof(EnumConverter<>).MakeGenericType(typeToConvert).GetConstructor(new Type[] { typeof(bool) });return (JsonConverter)ctor.Invoke(new object[] { enum2String });});}}/// <summary>/// 泛型枚举类型转换器/// </summary>/// <typeparam name="T"></typeparam>public sealed class EnumConverter<T> : JsonConverter<T> where T : struct, Enum{public EnumConverter(bool enum2String){this.enum2String = enum2String;}private static readonly TypeCode s_enumTypeCode = Type.GetTypeCode(typeof(T));private readonly bool enum2String;public override bool CanConvert(Type type){return type.IsEnum;}public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){switch (reader.TokenType){case JsonTokenType.String:var str = reader.GetString();return (T)Enum.Parse(typeof(T), str, true);case JsonTokenType.Number:switch (s_enumTypeCode){case TypeCode.Int32:{if (reader.TryGetInt32(out var value8)){return Unsafe.As<int, T>(ref value8);}break;}case TypeCode.UInt32:{if (reader.TryGetUInt32(out var value4)){return Unsafe.As<uint, T>(ref value4);}break;}case TypeCode.UInt64:{if (reader.TryGetUInt64(out var value6)){return Unsafe.As<ulong, T>(ref value6);}break;}case TypeCode.Int64:{if (reader.TryGetInt64(out var value2)){return Unsafe.As<long, T>(ref value2);}break;}case TypeCode.SByte:{if (reader.TryGetSByte(out var value7)){return Unsafe.As<sbyte, T>(ref value7);}break;}case TypeCode.Byte:{if (reader.TryGetByte(out var value5)){return Unsafe.As<byte, T>(ref value5);}break;}case TypeCode.Int16:{if (reader.TryGetInt16(out var value3)){return Unsafe.As<short, T>(ref value3);}break;}case TypeCode.UInt16:{if (reader.TryGetUInt16(out var value)){return Unsafe.As<ushort, T>(ref value);}break;}}throw new Exception($"无法从 {JsonTokenType.Number} 转为枚举!");default:throw new Exception($"无法从 {reader.TokenType} 转为枚举!");}}public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options){if (enum2String){writer.WriteStringValue(value.ToString());}else{switch (s_enumTypeCode){case TypeCode.Int32:writer.WriteNumberValue(Unsafe.As<T, int>(ref value));break;case TypeCode.UInt32:writer.WriteNumberValue(Unsafe.As<T, uint>(ref value));break;case TypeCode.UInt64:writer.WriteNumberValue(Unsafe.As<T, ulong>(ref value));break;case TypeCode.Int64:writer.WriteNumberValue(Unsafe.As<T, long>(ref value));break;case TypeCode.Int16:writer.WriteNumberValue(Unsafe.As<T, short>(ref value));break;case TypeCode.UInt16:writer.WriteNumberValue(Unsafe.As<T, ushort>(ref value));break;case TypeCode.Byte:writer.WriteNumberValue(Unsafe.As<T, byte>(ref value));break;case TypeCode.SByte:writer.WriteNumberValue(Unsafe.As<T, sbyte>(ref value));break;default:throw new Exception($"无法将 {s_enumTypeCode} 序列化!");}}}}}

处理 Dynamic 类型

    /// <summary>/// JsonElement转Dynamic类型/// </summary>public class JsonDynamicAccessor : DynamicObject{private readonly JsonElement _content;public JsonDynamicAccessor(JsonElement content){_content = content;}public override bool TryGetMember(GetMemberBinder binder, out dynamic result){if (_content.TryGetProperty(binder.Name, out JsonElement value)){result = Obtain(value);return true;}else{result = null;return false;}}private dynamic Obtain(in JsonElement element){switch (element.ValueKind){case JsonValueKind.String: return element.GetString();case JsonValueKind.Null: return null;case JsonValueKind.False: return false;case JsonValueKind.True: return true;case JsonValueKind.Number:if (element.TryGetInt64(out long longNumber)){return longNumber;}if (element.TryGetInt32(out int intNumber)){return intNumber;}if (element.TryGetDecimal(out decimal decimalNumber)){return decimalNumber;}if (element.TryGetDouble(out double doubleNumber)){return doubleNumber;}if (element.TryGetInt16(out short shortNumber)){return shortNumber;}break;default: break;}if (element.ValueKind == JsonValueKind.Array){return element.EnumerateArray().Select(item => Obtain(item)).ToList();}else{return new JsonDynamicAccessor(element);}}}

封装常用配置

    /// <summary>/// Json序列化扩展/// </summary>public static class JsonSerializeExtensions{public static IMvcBuilder AddMCodeJsonOptions(this IMvcBuilder builder,Action<JsonOptions> configure = null){builder.AddJsonOptions(options =>{// 设置要在转义字符串时使用的编码器,或为 null(要使用默认编码器的话)options.JsonSerializerOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; // 非ascii码转换// 是否在序列化和反序列化期间处理字段,默认值为 falseoptions.JsonSerializerOptions.IncludeFields = true;// 在序列化期间是否忽略只读字段.如果某字段用 readonly 关键字进行标记,则该字段为只读字段。 默认值为 falseoptions.JsonSerializerOptions.IgnoreReadOnlyFields = false;// 在序列化或反序列化期间何时忽略具有默认值的属性,默认值:Never属性总是被序列化和反序列化,与IgnoreNullValues配置无关。// WhenWritingNull:(如果其值为空,则忽略属性。这只应用于引用类型的属性和字段)options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.Never;// 指示属性名称在反序列化期间是否使用不区分大小写的比较,默认值为 falseoptions.JsonSerializerOptions.PropertyNameCaseInsensitive = true;// 指定用于将对象的属性名称转换为其他格式(例如 camel 大小写)的策略;若为 null,则保持属性名称不变。options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;// 反序列化过程中如何处理注释options.JsonSerializerOptions.ReadCommentHandling = System.Text.Json.JsonCommentHandling.Skip;// 该值指示要反序列化的 JSON 有效负载中是否允许(和忽略)对象或数组中 JSON 值的列表末尾多余的逗号。options.JsonSerializerOptions.AllowTrailingCommas = true;//允许 {"Prop":"NaN"} 浮点型,但不允许 {\"Prop\":NaN},这点无法做到与Newtonsoft兼容options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.AllowNamedFloatingPointLiterals;// 是否格式化文本options.JsonSerializerOptions.WriteIndented = true;// 处理循环引用类型options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.DateTimeConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.DateOnlyConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.TimeOnlyConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.LongConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.Int32Converter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.DecimalConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.BooleanConverter()); ;options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.StringConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.EnumConverter());options.JsonSerializerOptions.Converters.Add(new JsonConverterExtensions.NullAbleConverter());configure.Invoke(options);});return builder;}}builder.Services.AddControllers().AddMCodeJsonOptions();

封装 JsonHelper 帮助类

    /// <summary>/// Json序列化反序列化类/// </summary>public class JsonHelper{public static JsonSerializerOptions DefaultSerializerOptions{get{var options = new JsonSerializerOptions();// 设置要在转义字符串时使用的编码器,或为 null(要使用默认编码器的话)options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;// 是否在序列化和反序列化期间处理字段,默认值为 falseoptions.IncludeFields = true;// 在序列化期间是否忽略只读字段.如果某字段用 readonly 关键字进行标记,则该字段为只读字段。 默认值为 falseoptions.IgnoreReadOnlyFields = false;// 在序列化或反序列化期间何时忽略具有默认值的属性,默认值:Never属性总是被序列化和反序列化,与IgnoreNullValues配置无关。// WhenWritingNull:(如果其值为空,则忽略属性。这只应用于引用类型的属性和字段)options.DefaultIgnoreCondition = JsonIgnoreCondition.Never;// 指示属性名称在反序列化期间是否使用不区分大小写的比较,默认值为 falseoptions.PropertyNameCaseInsensitive = true;// 指定用于将对象的属性名称转换为其他格式(例如 camel 大小写)的策略;若为 null,则保持属性名称不变。options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;// 反序列化过程中如何处理注释options.ReadCommentHandling = JsonCommentHandling.Skip;// 该值指示要反序列化的 JSON 有效负载中是否允许(和忽略)对象或数组中 JSON 值的列表末尾多余的逗号。options.AllowTrailingCommas = true;//允许 {"Prop":"NaN"} 浮点型,但不允许 {\"Prop\":NaN},这点无法做到与Newtonsoft兼容options.NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.AllowNamedFloatingPointLiterals;// 是否格式化文本options.WriteIndented = true;// 处理循环引用类型options.ReferenceHandler = ReferenceHandler.IgnoreCycles;options.Converters.Add(new JsonConverterExtensions.DateTimeConverter());options.Converters.Add(new JsonConverterExtensions.DateOnlyConverter());options.Converters.Add(new JsonConverterExtensions.TimeOnlyConverter());options.Converters.Add(new JsonConverterExtensions.LongConverter());options.Converters.Add(new JsonConverterExtensions.Int32Converter());options.Converters.Add(new JsonConverterExtensions.DecimalConverter());options.Converters.Add(new JsonConverterExtensions.BooleanConverter()); ;options.Converters.Add(new JsonConverterExtensions.StringConverter());options.Converters.Add(new JsonConverterExtensions.EnumConverter());options.Converters.Add(new JsonConverterExtensions.NullAbleConverter());return options;}}public static T Deserialize<T>(string json, JsonSerializerOptions serializerOptions = null){if (string.IsNullOrEmpty(json)) return default;if (serializerOptions == null) serializerOptions = DefaultSerializerOptions;//值类型和String类型if (typeof(T).IsValueType || typeof(T) == typeof(string)){return (T)Convert.ChangeType(json, typeof(T));}// dynamic类型if (typeof(T) == typeof(object)){return (dynamic)new JsonDynamicAccessor(JsonSerializer.Deserialize<JsonElement>(json));}return JsonSerializer.Deserialize<T>(json, serializerOptions);}public static string Serialize<T>(T obj, JsonSerializerOptions serializerOptions = null){if (obj is null) return string.Empty;if (obj is string) return obj.ToString();if (serializerOptions == null) serializerOptions = DefaultSerializerOptions;return JsonSerializer.Serialize(obj, serializerOptions);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/660531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript高级:深浅拷贝

目录 1 引言 2 浅拷贝 2.1 拷贝数组 1.2 拷贝对象 3 赋值操作和浅拷贝的比较 4 深拷贝 4.1 前置知识 --> 递归函数 4.2 使用递归实现深拷贝 4.3 js库中的lodash里面的cloneDeep内部实现深拷贝 4.4 利用JSON实现深拷贝 深浅拷贝只针对引用数据类型 1 引言 假如我们…

如何在Windows系统使用Plex部署影音服务与公网访问本地资源【内网穿透】

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通…

人工智能时代:AI提示工程的奥秘 —— 驾驭大语言模型的秘密武器

文章目录 一、引言二、提示工程与大语言模型三、大语言模型的应用实践四、策略与技巧五、结语《AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型》亮点内容简介作者简介目录获取方式 一、引言 随着人工智能技术的飞速发展&#xff0c;大语言模型作为一种新…

如何发布自己的npm包:

1.创建一个打包组件或者库&#xff1a; 安装weback&#xff1a; 打开项目&#xff1a; 创建webpack.config.js,创建src目录 打包好了后发现两个js文件都被压缩了&#xff0c;我们想开发使用未压缩&#xff0c;生产使用压缩文件。 erserPlugin&#xff1a;&#xff08;推荐使用…

UAD155A0111 3BHE029110R0111

UAD155A0111 3BHE029110R0111 UAD155A0111 3BHE029110R0111 UAD155A0111 3BHE029110R0111如何通过CDMA模块实现车载终端数据通信 ... 包括单片机(rabbit2000)、GPS模块、CDMA 手机模块、GSM手机模块、铁电存储器、 ... 提取经纬度信息&#xff0c;通过GSM和 CDMA 模块分别采…

YIA主题如何关闭新版本升级提示?WordPress主题怎么取消升级提醒?

前两天YIA主题发布了升级到2.8版本&#xff0c;新增了一些功能&#xff0c;优化调整修复了一些功能&#xff0c;但是这些功能调整幅度不大&#xff0c;加上boke112百科使用的YIA主题已经进行了很多方面的个性化修改&#xff0c;所以就懒得升级了&#xff0c;但是每次进入WordPr…

Spring的事件监听机制

这里写自定义目录标题 1. 概述&#xff08;重点&#xff09;2. ApplicationEventMulticaster2.1 SimpleApplicationEventMulticaster2.2 AbstractApplicationEventMulticaster 3. ApplicationListener3.1 注册监听器3.2 自定义 4. SpringApplicationRunListeners 1. 概述&#…

Python接口自动化测试(接口状态)

本节开始&#xff0c;开始介绍python的接口自动化测试&#xff0c;首先需要搭建python开发环境&#xff0c;到https://www.python.org/下载python 版本直接安装就以了&#xff0c;建议 下载python2.7.11版本&#xff0c;当然&#xff0c;也是可以下载python最新版本的。 接口测…

纯干货,3步轻松生成智慧乡村3D场景!

临近春节返乡&#xff0c;网上有个话题又重新上了热门&#xff0c;“以你的专业&#xff0c;回到家乡能做什么贡献&#xff1f;”虽然很多人调侃&#xff0c;对家乡最大的贡献就是“离开家乡”&#xff0c;但其实现在农村老家的发展也离不开打工人在远方的支持。 比如AMRT3D引…

Docker基础(持续更新中)

# 第1步&#xff0c;去DockerHub查看nginx镜像仓库及相关信息# 第2步&#xff0c;拉取Nginx镜像 docker pull nginx# 第3步&#xff0c;查看镜像 docker images # 结果如下&#xff1a; REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 60…

【数学】【记忆化搜索 】【动态规划】964. 表示数字的最少运算符

作者推荐 【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数 本文涉及知识点 动态规划汇总 数学 记忆化搜索 LeetCoce964表示数字的最少运算符 给定一个正整数 x&#xff0c;我们将会写出一个形如 x (op1) x (op2) x (op3) x … 的表达式&#xff0c;其中每…

接口性能优化常见12式

目录 1.批处理 2.异步处理 3.空间换时间 4.预处理 5.池化思想 6.串行改并行 7.索引 8.避免大事务 9.优化程序结构 10.深分页问题 11.SQL优化 12.锁粒度避免过粗 1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场…

微服务—Docker

目录 初识Docker Docker与虚拟机的区别 镜像与容器 Docker架构 常见Docker命令 镜像命令 容器命令 数据卷挂载 直接挂载 初识Docker 在项目部署的过程中&#xff0c;如果出现大型项目组件较多&#xff0c;运行环境也较为复杂的情况&#xff0c;部署时会碰到一些问题&…

算法练习-逆波兰表达式求值(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;栈与队列 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c…

Plant, Cell Environment:DNA pull down技术助力揭示AP2/ERF类转录因子提高芍药耐高温能力的分子机制

芍药是一种传统的中药材&#xff0c;并且具有极高的欣赏价值&#xff0c;其生长发育经常受到高温胁迫的影响。褪黑素是一种内源性微分子吲哚胺化合物&#xff0c;在各种生物体中具有多种生理功能&#xff0c;大量研究表明调节与褪黑素生物合成相关的基因来提高植物对高温的耐受…

《区块链简易速速上手小册》第8章:区块链的技术挑战(2024 最新版)

文章目录 8.1 可扩展性问题8.1.1 基础知识8.1.2 主要案例&#xff1a;比特币的可扩展性挑战8.1.3 拓展案例 1&#xff1a;以太坊的可扩展性改进8.1.4 拓展案例 2&#xff1a;侧链和分层解决方案 8.2 安全性与隐私8.2.1 基础知识8.2.2 主要案例&#xff1a;比特币交易的安全性8.…

DVI接口如何连接HDMI接口显示器?DVI转HDMI转换器DHA

DVI转HDMI转换器DHA简介 DVI转HDMI转换器DHA能够将DVI信号和R/L音频信号输入转换成HDMI信号输出,独特的功能使其顺畅地整合到家庭影院中&#xff0c;并且播放出高品质的图像。主要用于数据监控中心、大型会议展示中心、学校及各个公司 DVI转HDMI转换器DHA特点 01.支持分辨率4K…

网络协议 TCP协议

网络协议 TCP协议 文章目录 网络协议 TCP协议1. TCP协议段格式2. 可靠传输保障机制2.1 确认应答2.2 超时重传 3. 连接保障机制3.1 三次握手&#xff08;建立连接&#xff09;3.2 四次挥手&#xff08;断开连接&#xff09;3.3 TCP状态转换过程 4. 传输效率保障机制4.1 滑动窗口…

MySQL原理(二)存储引擎(1)概述

一、存储引擎介绍 1、概念&#xff1a; &#xff08;1&#xff09;MySQL中的数据用各种不下同的技术存储在文件中&#xff0c;每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力&#xff0c;这些不同的技术以及配套的功能在MySQL中称为存储引擎…

【全csdn最前沿LVGL9】按钮的使用(lv_button)、标签的使用(lv_label)

文章目录 前言一、按钮概述二、按钮的使用2.1 创建一个按钮2.2 按钮的样式 三、标签概述四、标签的使用4.1 创建一个标签4.2 样式4.3 设置文本4.4 长文本模式4.5 文本选择4.6 文本对齐4.7 非常长的文本4.8 字体设置字体支持的Unicode字符字体列表特殊的字体 总结 前言 欢迎来到…