简介

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。

自定义转换器

  • 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的更多相关文章

  1. [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》

    [ASP.NET MVC2 系列]      [ASP.NET MVC2 系列] ASP.Net MVC教程之<在15分钟内用ASP.Net MVC创建一个电影数据库应用程序>       ...

  2. 在.Net Core 3.0中尝试新的System.Text.Json API

    .NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...

  3. .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法

    行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...

  4. Net core 2.x 升级 3.0 使用自带 System.Text.Json 时区 踩坑经历

    .Net Core 3.0 更新的东西很多,这里就不多做解释了,官方和博园大佬写得很详细 关于 Net Core 时区问题,在 2.1 版本的时候,因为用的是 Newtonsoft.Json,配置比较 ...

  5. .NET Core 内置的 System.Text.Json 使用注意

    System.Text.Json 是 .NET Core 3.0 新引入的高性能 json 解析.序列化.反序列化类库,武功高强,但毕竟初入江湖,炉火还没纯青,使用时需要注意,以下是我们在实现使用中遇 ...

  6. .net core中关于System.Text.Json的使用

    在.Net Framework的时候序列化经常使用Newtonsoft.Json插件来使用,而在.Net Core中自带了System.Text.Json,号称性能更好,今天抽空就来捣鼓一下. 使用起 ...

  7. [.Net Core 3.0+/.Net 5] System.Text.Json中时间格式化

    简介 .Net Core 3.0开始全新推出了一个名为System.Text.Json的Json解析库,用于序列化和反序列化Json,此库的设计是为了取代Json.Net(Newtonsoft.Jso ...

  8. .NET性能系列文章二:Newtonsoft.Json vs. System.Text.Json

    微软终于追上了? 图片来自 Glenn Carstens-Peters Unsplash 欢迎来到.NET性能系列的另一章.这个系列的特点是对.NET世界中许多不同的主题进行研究.基准和比较.正如标题 ...

  9. asp.net core系列 28 EF模型配置(字段,构造函数,拥有实体类型)

    一. 支持字段 EF允许读取或写入字段而不是一个属性.在使用实体类时,用面向对象的封装来限制或增强应用程序代码对数据访问的语义时,这可能很有用.无法使用数据注释配置.除了约定,还可以使用Fluent ...

  10. asp.net core系列 29 EF模型配置(查询类型,关系数据库建模)

    一.查询类型 此功能是EF Core 2.1中的新功能. EF Core除了实体类型之外,EF Core模型还可以包含查询类型,这些查询类型是针对“未映射到实体类型”的数据获取.比如视图,或只读数据表 ...

随机推荐

  1. Java 21 新特性:Unnamed Patterns and Variables

    Java 21中除了推出JEP 445:Unnamed Classes and Instance Main Methods之外,还有另外一个预览功能:未命名模式和变量(Unnamed Patterns ...

  2. POJ1426: Find The Multiple

    题目: 给定一个正整数n,请编写一个程序来寻找n的一个非零的倍数m,这个m应当在十进制表示时每一位上只包含0或者1.你可以假定n不大于200且m不多于100位. 提示:本题采用Special Judg ...

  3. Django 对实体的增删改查样例

    class UserInfo(models.Model): """ 人员信息 """ user_id = models.CharField( ...

  4. 五、java操作swift对象存储(官网样例)

    系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...

  5. lin UI微信小程序组件库

    https://doc.mini.talelin.com/start/ 所在文件夹,npm init 安装组件库, npm i lin-ui@0.8.7 选择"工具-构建npm".

  6. mongoose学习记录

    1 const mongoose = require('mongoose'); 2 3 mongoose.connect('mongodb://localhost/playground') 4 .th ...

  7. vue判断用户在页面停留时间是否超时

    需求 当用户停留超过15分钟后,用户提交订单,提示用户超时并重新加载页面 代码 data () { return { // 超时定时器 overTimer: null, // 是否超时 isOvert ...

  8. 我发现明显产品bug啦

    1.  百度云在下载时,如果选中的文件过多,在点击下载后,不能即时取消所有的下载项! 如下图,点击""全部取消" 出现在列表中项全部消失,但后续新的项继续出现,仍在下载, ...

  9. spring启动流程 (1) 流程概览

    本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启动流程. 创建AnnotationConfigApplicationContext Annot ...

  10. Go-数据类型-函数

    函数类型 函数声明本质上是定义了函数类型的变量 package main import "fmt" // 定义了函数,本质上是在全局作用域中声明了一个函数类型的变量 info 其类 ...