UNIVPLMDataIntegration/Admin.NET/Admin.NET.Core/Utils/CustomJson/CustomJsonConverter.cs

222 lines
8.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Admin.NET.Core;
/// <summary>
/// 自定义JSON转换器
/// </summary>
public class CustomJsonConverter : JsonConverterFactory
{
/// <summary>
/// 判断是否可以转换指定类型
/// </summary>
/// <param name="typeToConvert">要转换的类型</param>
/// <returns>是否可以转换</returns>
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert.GetProperties()
.Any(p => p.GetCustomAttribute<CustomJsonPropertyAttribute>() != null);
}
/// <summary>
/// 创建指定类型的转换器实例
/// </summary>
/// <param name="type">要转换的类型</param>
/// <param name="options">JSON序列化选项</param>
/// <returns>JSON转换器实例</returns>
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
{
var converterType = typeof(CustomConverter<>).MakeGenericType(type);
return (JsonConverter)Activator.CreateInstance(converterType, options);
}
/// <summary>
/// 自定义转换器实现类
/// </summary>
/// <typeparam name="T">要转换的类型</typeparam>
private class CustomConverter<T> : JsonConverter<T>
{
/// <summary>
/// 基础JSON序列化选项
/// </summary>
private readonly JsonSerializerOptions _baseOptions;
/// <summary>
/// JSON属性名到对象属性的映射字典
/// </summary>
private readonly Dictionary<string, PropertyInfo> _jsonToPropertyMap;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="baseOptions">基础JSON序列化选项</param>
public CustomConverter(JsonSerializerOptions baseOptions)
{
_baseOptions = new JsonSerializerOptions(baseOptions);
_jsonToPropertyMap = CreatePropertyMap();
}
/// <summary>
/// 创建属性映射字典
/// </summary>
/// <returns>属性映射字典</returns>
private Dictionary<string, PropertyInfo> CreatePropertyMap()
{
var map = new Dictionary<string, PropertyInfo>(StringComparer.OrdinalIgnoreCase);
foreach (var prop in typeof(T).GetProperties())
{
var customAttr = prop.GetCustomAttribute<CustomJsonPropertyAttribute>();
if (customAttr != null)
{
map[customAttr.Name] = prop;
}
else
{
var jsonName = _baseOptions.PropertyNamingPolicy?.ConvertName(prop.Name) ?? prop.Name;
map[jsonName] = prop;
}
}
return map;
}
/// <summary>
/// 反序列化JSON为对象
/// </summary>
/// <param name="reader">JSON读取器</param>
/// <param name="typeToConvert">要转换的类型</param>
/// <param name="options">JSON序列化选项</param>
/// <returns>反序列化后的对象</returns>
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null) return default;
// 创建实例并设置默认值
var instance = Activator.CreateInstance<T>();
object GetDefaultValue(Type type) => type.IsValueType ? Activator.CreateInstance(type) : null;
foreach (var prop in typeof(T).GetProperties().Where(p => p.CanWrite))
prop.SetValue(instance, GetDefaultValue(prop.PropertyType));
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
if (_jsonToPropertyMap.TryGetValue(propertyName!, out var prop))
{
reader.Read();
var value = DeserializeWithCustomFormat(ref reader, prop, _baseOptions);
prop.SetValue(instance, value);
}
else
{
reader.Skip();
}
}
}
return instance;
}
/// <summary>
/// 序列化对象为JSON
/// </summary>
/// <param name="writer">JSON写入器</param>
/// <param name="value">要序列化的对象</param>
/// <param name="options">JSON序列化选项</param>
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (var prop in typeof(T).GetProperties())
{
var propValue = prop.GetValue(value);
if (propValue == null && _baseOptions.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull)
continue;
var customAttr = prop.GetCustomAttribute<CustomJsonPropertyAttribute>();
var jsonName = customAttr?.Name ?? ToCamelCase(prop.Name);
writer.WritePropertyName(jsonName);
// 处理日期格式化
if (!string.IsNullOrEmpty(customAttr?.DateFormat))
{
if (propValue is DateTime dateTime)
{
writer.WriteStringValue(dateTime.ToString(customAttr.DateFormat));
}
else if (prop.PropertyType == typeof(DateTime?) && propValue != null)
{
var nullableDateTime = (DateTime?)propValue;
writer.WriteStringValue(nullableDateTime.Value.ToString(customAttr.DateFormat));
}
else
{
JsonSerializer.Serialize(writer, propValue, prop.PropertyType, _baseOptions);
}
}
else
{
JsonSerializer.Serialize(writer, propValue, prop.PropertyType, _baseOptions);
}
}
writer.WriteEndObject();
}
/// <summary>
/// 转换属性名
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private string ToCamelCase(string name)
{
if (string.IsNullOrEmpty(name)) return name;
return char.ToLowerInvariant(name[0]) + name.Substring(1);
}
/// <summary>
/// 反序列化JSON为对象处理自定义格式
/// </summary>
private object DeserializeWithCustomFormat(ref Utf8JsonReader reader, PropertyInfo prop, JsonSerializerOptions options)
{
var customAttr = prop.GetCustomAttribute<CustomJsonPropertyAttribute>();
// 特殊处理日期类型
if (!string.IsNullOrEmpty(customAttr?.DateFormat))
{
if (prop.PropertyType == typeof(DateTime) && reader.TokenType == JsonTokenType.String)
{
var dateString = reader.GetString();
if (DateTime.TryParseExact(dateString, customAttr.DateFormat, null, DateTimeStyles.None, out var dateTime))
{
return dateTime;
}
}
else if (prop.PropertyType == typeof(DateTime?) && reader.TokenType == JsonTokenType.String)
{
var dateString = reader.GetString();
if (DateTime.TryParseExact(dateString, customAttr.DateFormat, null, DateTimeStyles.None, out var dateTime))
{
return (DateTime?)dateTime;
}
return null;
}
}
// 默认处理
return JsonSerializer.Deserialize(ref reader, prop.PropertyType, options);
}
}
}