文章目录
简介
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 的值类型 | ⚠️ ⚠ |
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);
}