using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using InABox.Clients; using JetBrains.Annotations; using Newtonsoft.Json; namespace InABox.Core { public interface ISerializeBinary { public void SerializeBinary(BinaryWriter writer); public void DeserializeBinary(BinaryReader reader); } public static class Serialization { private static JsonSerializerSettings? _serializerSettings; private static JsonSerializerSettings SerializerSettings(bool indented = true) { if (_serializerSettings == null) { _serializerSettings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.DateTime, DateFormatHandling = DateFormatHandling.IsoDateFormat, DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind }; _serializerSettings.Converters.Add(new DataTableJsonConverter()); //serializerSettings.Converters.Add(new DateTimeJsonConverter()); _serializerSettings.Converters.Add(new FilterJsonConverter()); _serializerSettings.Converters.Add(new ColumnJsonConverter()); _serializerSettings.Converters.Add(new SortOrderJsonConverter()); _serializerSettings.Converters.Add(new UserPropertiesJsonConverter()); } _serializerSettings.Formatting = indented ? Formatting.Indented : Formatting.None; return _serializerSettings; } public static string Serialize(object? o, bool indented = false) { var json = JsonConvert.SerializeObject(o, SerializerSettings(indented)); return json; } public static void Serialize(object o, Stream stream, bool indented = false) { var settings = SerializerSettings(indented); using (var sw = new StreamWriter(stream)) { using (JsonWriter writer = new JsonTextWriter(sw)) { var serializer = JsonSerializer.Create(settings); serializer.Serialize(writer, o); } } } public static void DeserializeInto(string json, object target) { JsonConvert.PopulateObject(json, target, SerializerSettings()); } [return: MaybeNull] public static T Deserialize(Stream? stream, bool strict = false) { if (stream == null) return default; try { var settings = SerializerSettings(); using var sr = new StreamReader(stream); using JsonReader reader = new JsonTextReader(sr); var serializer = JsonSerializer.Create(settings); return serializer.Deserialize(reader); } catch (Exception e) { if (strict) throw; Logger.Send(LogType.Error, ClientFactory.UserID, $"Error in Deserialize<{typeof(T)}>(): {e.Message}"); return default; } } public static object? Deserialize(Type type, Stream? stream) { if (stream == null) return null; object? result = null; var settings = SerializerSettings(); using (var sr = new StreamReader(stream)) { using (JsonReader reader = new JsonTextReader(sr)) { var serializer = JsonSerializer.Create(settings); result = serializer.Deserialize(reader, type); } } return result; } [return: MaybeNull] public static T Deserialize(string? json, bool strict = false) // where T : new() { var ret = default(T); if (string.IsNullOrWhiteSpace(json)) return ret; try { var settings = SerializerSettings(); //if (typeof(T).IsSubclassOf(typeof(BaseObject))) //{ // ret = Activator.CreateInstance(); // (ret as BaseObject).SetObserving(false); // JsonConvert.PopulateObject(json, ret, settings); // (ret as BaseObject).SetObserving(true); //} //else if (typeof(T).IsArray) { object o = Array.CreateInstance(typeof(T).GetElementType(), 0); ret = (T)o; } else { ret = JsonConvert.DeserializeObject(json, settings); } } catch (Exception) { if (strict) { throw; } ret = Activator.CreateInstance(); } return ret; } public static object? Deserialize(Type T, string json) // where T : new() { var ret = T.GetDefault(); if (string.IsNullOrWhiteSpace(json)) return ret; try { var settings = SerializerSettings(); //if (typeof(T).IsSubclassOf(typeof(BaseObject))) //{ // ret = Activator.CreateInstance(); // (ret as BaseObject).SetObserving(false); // JsonConvert.PopulateObject(json, ret, settings); // (ret as BaseObject).SetObserving(true); //} //else if (T.IsArray) { object o = Array.CreateInstance(T.GetElementType(), 0); ret = o; } else { ret = JsonConvert.DeserializeObject(json, T, settings); } } catch (Exception) { ret = Activator.CreateInstance(T); } return ret; } #region Binary Serialization public static byte[] WriteBinary(this ISerializeBinary obj) { using var stream = new MemoryStream(); obj.SerializeBinary(new BinaryWriter(stream)); return stream.ToArray(); } public static T ReadBinary(byte[] data) where T : ISerializeBinary, new() => (T)ReadBinary(typeof(T), data); public static T ReadBinary(Stream stream) where T : ISerializeBinary, new() => (T)ReadBinary(typeof(T), stream); public static object ReadBinary(Type T, byte[] data) { using var stream = new MemoryStream(data); return ReadBinary(T, stream); } public static object ReadBinary(Type T, Stream stream) { var obj = (Activator.CreateInstance(T) as ISerializeBinary)!; obj.DeserializeBinary(new BinaryReader(stream)); return obj; } #endregion } }