簡介
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
{
private static readonly JsonSerializerOptions _defaultSerializerOptions;
static JsonHelper()
{
var options = new JsonSerializerOptions();
// 設置要在轉義字符串時使用的編碼器,或爲 null(要使用默認編碼器的話)
options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
// 是否在序列化和反序列化期間處理字段,默認值爲 false
options.IncludeFields = true;
// 在序列化期間是否忽略只讀字段.如果某字段用 readonly 關鍵字進行標記,則該字段爲只讀字段。 默認值爲 false
options.IgnoreReadOnlyFields = false;
// 在序列化或反序列化期間何時忽略具有默認值的屬性,默認值:Never屬性總是被序列化和反序列化,與IgnoreNullValues配置無關。
// WhenWritingNull:(如果其值爲空,則忽略屬性。這隻應用於引用類型的屬性和字段)
options.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.Never;
// 指示屬性名稱在反序列化期間是否使用不區分大小寫的比較,默認值爲 false
options.PropertyNameCaseInsensitive = true;
// 指定用於將對象的屬性名稱轉換爲其他格式(例如 camel 大小寫)的策略;若爲 null,則保持屬性名稱不變。
options.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
// 反序列化過程中如何處理註釋
options.ReadCommentHandling = System.Text.Json.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());
_defaultSerializerOptions = 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);
}