Asp .Net Core 系列:Asp .Net Core 配置 System.Text.Json
简介
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
所有配置
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
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 的值类型 |
️ |
DateTimeZoneHandling 、DateFormatString 设置 |
️ |
JsonConvert.PopulateObject 方法 |
️ |
支持 System.Runtime.Serialization 特性 |
️ |
JsonObjectAttribute |
️ |
允许不带引号的属性名称 | 设计上不受支持 |
字符串值前后允许单引号 | 设计上不受支持 |
对字符串属性允许非字符串 JSON 值 | 设计上不受支持 |
TypeNameHandling.All 全局设置 |
设计上不受支持 |
支持 JsonPath 查询 |
不支持 |
可配置的限制 | 不支持 |
无实体类型下操作 Json
类似 Newtonsoft.Json,在没有实体类的情况下,也可以使用 JsonNode/JsonValue/JsonArray/JsonObject 操作 json。
自定义转换器
- 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码转换
// 是否在序列化和反序列化期间处理字段,默认值为 false
options.JsonSerializerOptions.IncludeFields = true;
// 在序列化期间是否忽略只读字段.如果某字段用 readonly 关键字进行标记,则该字段为只读字段。 默认值为 false
options.JsonSerializerOptions.IgnoreReadOnlyFields = false;
// 在序列化或反序列化期间何时忽略具有默认值的属性,默认值:Never属性总是被序列化和反序列化,与IgnoreNullValues配置无关。
// WhenWritingNull:(如果其值为空,则忽略属性。这只应用于引用类型的属性和字段)
options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.Never;
// 指示属性名称在反序列化期间是否使用不区分大小写的比较,默认值为 false
options.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;
// 是否在序列化和反序列化期间处理字段,默认值为 false
options.IncludeFields = true;
// 在序列化期间是否忽略只读字段.如果某字段用 readonly 关键字进行标记,则该字段为只读字段。 默认值为 false
options.IgnoreReadOnlyFields = false;
// 在序列化或反序列化期间何时忽略具有默认值的属性,默认值:Never属性总是被序列化和反序列化,与IgnoreNullValues配置无关。
// WhenWritingNull:(如果其值为空,则忽略属性。这只应用于引用类型的属性和字段)
options.DefaultIgnoreCondition = JsonIgnoreCondition.Never;
// 指示属性名称在反序列化期间是否使用不区分大小写的比较,默认值为 false
options.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);
}
Asp .Net Core 系列:Asp .Net Core 配置 System.Text.Json的更多相关文章
- [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》
[ASP.NET MVC2 系列] [ASP.NET MVC2 系列] ASP.Net MVC教程之<在15分钟内用ASP.Net MVC创建一个电影数据库应用程序> ...
- 在.Net Core 3.0中尝试新的System.Text.Json API
.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...
- .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法
行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...
- Net core 2.x 升级 3.0 使用自带 System.Text.Json 时区 踩坑经历
.Net Core 3.0 更新的东西很多,这里就不多做解释了,官方和博园大佬写得很详细 关于 Net Core 时区问题,在 2.1 版本的时候,因为用的是 Newtonsoft.Json,配置比较 ...
- .NET Core 内置的 System.Text.Json 使用注意
System.Text.Json 是 .NET Core 3.0 新引入的高性能 json 解析.序列化.反序列化类库,武功高强,但毕竟初入江湖,炉火还没纯青,使用时需要注意,以下是我们在实现使用中遇 ...
- .net core中关于System.Text.Json的使用
在.Net Framework的时候序列化经常使用Newtonsoft.Json插件来使用,而在.Net Core中自带了System.Text.Json,号称性能更好,今天抽空就来捣鼓一下. 使用起 ...
- [.Net Core 3.0+/.Net 5] System.Text.Json中时间格式化
简介 .Net Core 3.0开始全新推出了一个名为System.Text.Json的Json解析库,用于序列化和反序列化Json,此库的设计是为了取代Json.Net(Newtonsoft.Jso ...
- .NET性能系列文章二:Newtonsoft.Json vs. System.Text.Json
微软终于追上了? 图片来自 Glenn Carstens-Peters Unsplash 欢迎来到.NET性能系列的另一章.这个系列的特点是对.NET世界中许多不同的主题进行研究.基准和比较.正如标题 ...
- asp.net core系列 28 EF模型配置(字段,构造函数,拥有实体类型)
一. 支持字段 EF允许读取或写入字段而不是一个属性.在使用实体类时,用面向对象的封装来限制或增强应用程序代码对数据访问的语义时,这可能很有用.无法使用数据注释配置.除了约定,还可以使用Fluent ...
- asp.net core系列 29 EF模型配置(查询类型,关系数据库建模)
一.查询类型 此功能是EF Core 2.1中的新功能. EF Core除了实体类型之外,EF Core模型还可以包含查询类型,这些查询类型是针对“未映射到实体类型”的数据获取.比如视图,或只读数据表 ...
随机推荐
- Java 21 新特性:Unnamed Patterns and Variables
Java 21中除了推出JEP 445:Unnamed Classes and Instance Main Methods之外,还有另外一个预览功能:未命名模式和变量(Unnamed Patterns ...
- POJ1426: Find The Multiple
题目: 给定一个正整数n,请编写一个程序来寻找n的一个非零的倍数m,这个m应当在十进制表示时每一位上只包含0或者1.你可以假定n不大于200且m不多于100位. 提示:本题采用Special Judg ...
- Django 对实体的增删改查样例
class UserInfo(models.Model): """ 人员信息 """ user_id = models.CharField( ...
- 五、java操作swift对象存储(官网样例)
系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...
- lin UI微信小程序组件库
https://doc.mini.talelin.com/start/ 所在文件夹,npm init 安装组件库, npm i lin-ui@0.8.7 选择"工具-构建npm".
- mongoose学习记录
1 const mongoose = require('mongoose'); 2 3 mongoose.connect('mongodb://localhost/playground') 4 .th ...
- vue判断用户在页面停留时间是否超时
需求 当用户停留超过15分钟后,用户提交订单,提示用户超时并重新加载页面 代码 data () { return { // 超时定时器 overTimer: null, // 是否超时 isOvert ...
- 我发现明显产品bug啦
1. 百度云在下载时,如果选中的文件过多,在点击下载后,不能即时取消所有的下载项! 如下图,点击""全部取消" 出现在列表中项全部消失,但后续新的项继续出现,仍在下载, ...
- spring启动流程 (1) 流程概览
本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启动流程. 创建AnnotationConfigApplicationContext Annot ...
- Go-数据类型-函数
函数类型 函数声明本质上是定义了函数类型的变量 package main import "fmt" // 定义了函数,本质上是在全局作用域中声明了一个函数类型的变量 info 其类 ...