using System; using System.Diagnostics; using System.IO.Abstractions; using System.Linq; using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; namespace Quadarax.Foundation.Core.Json { public class Binder { private IFileSystem _fileSystem; public JsonSerializerOptions SerializerOptions {get;private set;} public Binder(JsonSerializerOptions options): this(new FileSystem(), options) { } public Binder(IFileSystem fileSystemAbstraction, JsonSerializerOptions options) { _fileSystem = fileSystemAbstraction ?? throw new ArgumentNullException(nameof(fileSystemAbstraction)); SerializerOptions = options; } public Binder(IFileSystem fileSystemAbstraction, bool isPrettyPrint = true, bool isIgnoringNullValues = true, int maxDepth = 100) { _fileSystem = fileSystemAbstraction ?? throw new ArgumentNullException(nameof(fileSystemAbstraction)); var jsonOpt = new JsonSerializerOptions { IgnoreNullValues = isIgnoringNullValues, WriteIndented = isPrettyPrint, PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, MaxDepth = maxDepth }; jsonOpt.Converters.Add(new JsonStringEnumConverter()); SerializerOptions = jsonOpt; } public TObject Load(string fileName) { return (TObject) Load(fileName, typeof(TObject)); } public object Load(string fileName, Type targetType) { if (targetType == null) throw new ArgumentNullException(nameof(targetType)); if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException(nameof(fileName)); using (var reader = _fileSystem.File.OpenText(fileName)) { var result = JsonSerializer.Deserialize(reader.ReadToEnd(),targetType, SerializerOptions); return result; } } public object LoadFromString(string jsonString, Type targetType) { if (targetType == null) throw new ArgumentNullException(nameof(targetType)); if (string.IsNullOrEmpty(jsonString)) throw new ArgumentNullException(nameof(jsonString)); var result = JsonSerializer.Deserialize(jsonString,targetType, SerializerOptions); return result; } public void LoadTo(string fileName, object target, Type targetType) { if (targetType == null) throw new ArgumentNullException(nameof(targetType)); if (target == null) throw new ArgumentNullException(nameof(target)); var shadow = Load(fileName, targetType); foreach (var property in shadow.GetType().GetProperties()) { if (target.GetType().GetProperties().Any(x => x.Name == property.Name && property.GetValue(shadow) != null)) { if (property.GetType().IsClass && property.PropertyType.Assembly.FullName == targetType.Assembly.FullName) { var mapMethod = typeof(Binder).GetMethod("LoadTo"); var genericMethod = mapMethod.MakeGenericMethod(property.GetValue(shadow).GetType()); var obj2 = genericMethod.Invoke(null, new object[] { property.GetValue(shadow), JsonSerializer.Serialize(property.GetValue(shadow)) }); foreach (var property2 in obj2.GetType().GetProperties()) { if (property2.GetValue(obj2) != null) { property.GetValue(target).GetType().GetProperty(property2.Name).SetValue(property.GetValue(target), property2.GetValue(obj2)); } } } else if (property.CanWrite) { property.SetValue(target, property.GetValue(shadow)); } } } } public void LoadFromStringTo(string jsonString, object target, Type targetType) { if (targetType == null) throw new ArgumentNullException(nameof(targetType)); if (target == null) throw new ArgumentNullException(nameof(target)); var shadow = LoadFromString(jsonString, targetType); foreach (var property in shadow.GetType().GetProperties()) { if (target.GetType().GetProperties().Any(x => x.Name == property.Name && property.GetValue(shadow) != null)) { if (property.GetType().IsClass && property.PropertyType.Assembly.FullName == targetType.Assembly.FullName) { var mapMethod = typeof(Binder).GetMethod("LoadFromStringTo"); var genericMethod = mapMethod.MakeGenericMethod(property.GetValue(shadow).GetType()); var obj2 = genericMethod.Invoke(null, new object[] { property.GetValue(shadow), JsonSerializer.Serialize(property.GetValue(shadow)) }); foreach (var property2 in obj2.GetType().GetProperties()) { if (property2.GetValue(obj2) != null) { property.GetValue(target).GetType().GetProperty(property2.Name).SetValue(property.GetValue(target), property2.GetValue(obj2)); } } } else if (property.CanWrite) { property.SetValue(target, property.GetValue(shadow)); } } } } public void LoadTo(string fileName, TObject target) { LoadTo(fileName, target, typeof(TObject)); } public void Save(string fileName, TObject bindingObject) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullException(nameof(fileName)); if (bindingObject==null) throw new ArgumentNullException(nameof(bindingObject)); var configuration = JsonSerializer.SerializeToUtf8Bytes(bindingObject,SerializerOptions); using (var writer = _fileSystem.File.Create(fileName)) { writer.Write(configuration); writer.Flush(); } } public string SaveToString(TObject bindingObject) { if (bindingObject==null) throw new ArgumentNullException(nameof(bindingObject)); return JsonSerializer.Serialize(bindingObject,bindingObject.GetType()); } } }