diff --git a/AyCode.Core/Extensions/SerializeObjectExtensions.cs b/AyCode.Core/Extensions/SerializeObjectExtensions.cs index 92e05fb..d145687 100644 --- a/AyCode.Core/Extensions/SerializeObjectExtensions.cs +++ b/AyCode.Core/Extensions/SerializeObjectExtensions.cs @@ -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(this T source) => JsonConvert.SerializeObject(source, Options); - public static string ToJson(this IQueryable source) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, Options); - public static string ToJson(this IEnumerable source) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, Options); - - public static T? JsonTo(this string json) + public static string ToJson(this T source, JsonSerializerSettings? options = null) => JsonConvert.SerializeObject(source, options ?? Options); + public static string ToJson(this IQueryable source, JsonSerializerSettings? options = null) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, options ?? Options); + public static string ToJson(this IEnumerable source, JsonSerializerSettings? options = null) where T : class, IAcSerializableToJson => JsonConvert.SerializeObject(source, options ?? Options); + + public static T? JsonTo(this string json, JsonSerializerSettings? options = null) { if (json.StartsWith("\"") && json.EndsWith("\"")) json = Regex.Unescape(json).TrimStart('"').TrimEnd('"'); - return JsonConvert.DeserializeObject(json, Options); + return JsonConvert.DeserializeObject(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); } /// @@ -47,9 +49,10 @@ public static class SerializeObjectExtensions /// /// /// + /// /// [return: NotNullIfNotNull(nameof(src))] - public static TDestination? CloneTo(this object? src) where TDestination : class => src?.ToJson().JsonTo(); + public static TDestination? CloneTo(this object? src, JsonSerializerSettings? options = null) where TDestination : class => src?.ToJson(options).JsonTo(options); //public static string ToJson(this Expression source) => JsonConvert.SerializeObject(source, Options); @@ -58,4 +61,65 @@ public static class SerializeObjectExtensions public static T MessagePackTo(this byte[] message) => MessagePackSerializer.Deserialize(message); public static T MessagePackTo(this byte[] message, MessagePackSerializerOptions options) => MessagePackSerializer.Deserialize(message, options); -} \ No newline at end of file +} + +public class IgnoreAndRenamePropertySerializerContractResolver : DefaultContractResolver +{ + private readonly Dictionary> _ignores = new(); + private readonly Dictionary> _includes = new(); + private readonly Dictionary> _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(); + + _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; + } +}