Implement IgnoreAndRenamePropertySerializerContractResolver

This commit is contained in:
Loretta 2025-10-31 13:51:39 +01:00
parent a24f0c1681
commit c1a707139c
1 changed files with 80 additions and 16 deletions

View File

@ -1,10 +1,12 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using AyCode.Core.Interfaces;
using MessagePack.Resolvers;
using AyCode.Core.Interfaces;
using MessagePack;
using MessagePack.Resolvers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
namespace AyCode.Core.Extensions;
@ -16,30 +18,30 @@ public static class SerializeObjectExtensions
//TypeNameHandling = TypeNameHandling.All,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
NullValueHandling = NullValueHandling.Ignore,
////System.Text.Json
//ReferenceHandler.Preserve
//ReferenceHandler.IgnoreCycles
};
public static string ToJson<T>(this T source) => JsonConvert.SerializeObject(source, Options);
public static string ToJson<T>(this IQueryable<T> source) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, Options);
public static string ToJson<T>(this IEnumerable<T> source) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, Options);
public static T? JsonTo<T>(this string json)
public static string ToJson<T>(this T source, JsonSerializerSettings? options = null) => JsonConvert.SerializeObject(source, options ?? Options);
public static string ToJson<T>(this IQueryable<T> source, JsonSerializerSettings? options = null) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, options ?? Options);
public static string ToJson<T>(this IEnumerable<T> source, JsonSerializerSettings? options = null) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, options ?? Options);
public static T? JsonTo<T>(this string json, JsonSerializerSettings? options = null)
{
if (json.StartsWith("\"") && json.EndsWith("\"")) json = Regex.Unescape(json).TrimStart('"').TrimEnd('"');
return JsonConvert.DeserializeObject<T>(json, Options);
return JsonConvert.DeserializeObject<T>(json, options ?? Options);
}
public static object? JsonTo(this string json, Type toType)
public static object? JsonTo(this string json, Type toType, JsonSerializerSettings? options = null)
{
if (json.StartsWith("\"") && json.EndsWith("\"")) json = Regex.Unescape(json).TrimStart('"').TrimEnd('"');
return JsonConvert.DeserializeObject(json, toType, Options);
return JsonConvert.DeserializeObject(json, toType, options ?? Options);
}
/// <summary>
@ -47,9 +49,10 @@ public static class SerializeObjectExtensions
/// </summary>
/// <typeparam name="TDestination"></typeparam>
/// <param name="src"></param>
/// <param name="options"></param>
/// <returns></returns>
[return: NotNullIfNotNull(nameof(src))]
public static TDestination? CloneTo<TDestination>(this object? src) where TDestination : class => src?.ToJson().JsonTo<TDestination>();
public static TDestination? CloneTo<TDestination>(this object? src, JsonSerializerSettings? options = null) where TDestination : class => src?.ToJson(options).JsonTo<TDestination>(options);
//public static string ToJson(this Expression source) => JsonConvert.SerializeObject(source, Options);
@ -58,4 +61,65 @@ public static class SerializeObjectExtensions
public static T MessagePackTo<T>(this byte[] message) => MessagePackSerializer.Deserialize<T>(message);
public static T MessagePackTo<T>(this byte[] message, MessagePackSerializerOptions options) => MessagePackSerializer.Deserialize<T>(message, options);
}
}
public class IgnoreAndRenamePropertySerializerContractResolver : DefaultContractResolver
{
private readonly Dictionary<Type, HashSet<string>> _ignores = new();
private readonly Dictionary<Type, HashSet<string>> _includes = new();
private readonly Dictionary<Type, Dictionary<string, string>> _renames = new();
public void IgnoreProperty(Type type, params string[] jsonPropertyNames)
{
if (!_ignores.ContainsKey(type)) _ignores[type] = [];
foreach (var prop in jsonPropertyNames) _ignores[type].Add(prop);
}
public void IncludesProperty(Type type, params string[] jsonPropertyNames)
{
if (!_includes.ContainsKey(type)) _includes[type] = [];
foreach (var prop in jsonPropertyNames) _includes[type].Add(prop);
}
public void RenameProperty(Type type, string propertyName, string newJsonPropertyName)
{
if (!_renames.ContainsKey(type)) _renames[type] = new Dictionary<string, string>();
_renames[type][propertyName] = newJsonPropertyName;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (IsIgnored(property.DeclaringType, property.PropertyName) || !IsIncluded(property.DeclaringType, property.PropertyName))
{
property.ShouldSerialize = i => false;
property.Ignored = true;
}
if (IsRenamed(property.DeclaringType, property.PropertyName, out var newJsonPropertyName))
property.PropertyName = newJsonPropertyName;
return property;
}
private bool IsIgnored(Type type, string jsonPropertyName)
{
return _ignores.ContainsKey(type) && _ignores[type].Contains(jsonPropertyName);
}
private bool IsIncluded(Type type, string jsonPropertyName)
{
return _includes.Count == 0 || (_includes.ContainsKey(type) && _includes[type].Contains(jsonPropertyName));
}
private bool IsRenamed(Type type, string jsonPropertyName, out string? newJsonPropertyName)
{
if (_renames.TryGetValue(type, out var renames) && renames.TryGetValue(jsonPropertyName, out newJsonPropertyName)) return true;
newJsonPropertyName = null;
return false;
}
}