简介

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. ICASSP 2022 | 前沿音视频成果分享:基于可变形卷积的压缩视频质量增强网络

    阿里云视频云视频编码与增强技术团队最新研究成果论文<基于可变形卷积的压缩视频质量增强网络>(Deformable Convolution Dense Network for Compres ...

  2. CO40/CO41转生产订单下达时不能创建采购申请

    一.配置 CO01创建生产订单,创建时生成采购申请,改为下达时创建采购申请.通过配置,将预留/采购申请 更改为2即可. 但是CO41和CO40通过配置,并不能达到更改预留/采购申请 为2. 二.调试源 ...

  3. three.js项目引入vue,因代码编写不当导致的严重影响性能的问题,卡顿掉帧严重

    three.js项目引入vue,因代码编写不当导致的严重影响性能的问题,卡顿掉帧严重 问题排查 使用谷歌浏览器的Performance分析页面性能 可以看到vue.js的reactiveGetter方 ...

  4. 【QT 学习之路】事件

    事件(event)是由系统或者 Qt 本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事 ...

  5. Mynavi Programming Contest 2021(AtCoder Beginner Contest 201)A ~ E题题解

    A - Tiny Arithmetic Sequence 水题,判断3个数是否能构成等差数列 void solve() { int a, b, c; cin >> a >> b ...

  6. SpringCloud学习 系列三、 创建一个没有使用springCloud的服务提供者和消费者

    系列导航 SpringCloud学习 系列一. 前言-为什么要学习微服务 SpringCloud学习 系列二. 简介 SpringCloud学习 系列三. 创建一个没有使用springCloud的服务 ...

  7. MyBatis06——动态SQL

    动态SQL if choose (when, otherwise) trim (where, set) foreach 搭建环境 1.搭建数据库 CREATE TABLE `blog` ( `id` ...

  8. 【水一篇】骚操作之net 6的winform启动的同时启动Net 6 WebApi【同一套代码】

    引言 有段时间没有写博客了,不知道写什么,加上最近一直在玩单片机方面的东西,所以有一些懈怠.首先呢,为什么会有这么一个问题,是在一个QQ群里,有看到有人提问,能不能在启动Winform的同时去启动一个 ...

  9. [转帖]Oracle中unicode的几种不同字符编码模式

    https://zhuanlan.zhihu.com/p/668340691#   在Oracle中unicode字符集中,存在以下几种不同unicode字符集的编码模式 AL32UTF8 UTF8 ...

  10. 抓取java堆栈失败的思考-Safepoint等的学习

    抓取java堆栈失败的思考-Safepoint等的学习 背景 前期解决问题都是靠抓取进程堆栈 jstack,后者是jmap到内存dump的方式来进行分析. 最近连续有两个比较大的项目出现了抓取dump ...