using Newtonsoft.Json; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Tango.Core.Bson { public static class BsonConvert { private static BsonUtcSerializer _serializer; static BsonConvert() { _serializer = new BsonUtcSerializer(); } public static byte[] Serialize(Object obj) { MemoryStream ms = new MemoryStream(); using (BsonWriter writer = new BsonWriter(ms)) { _serializer.Serialize(writer, obj); return ms.ToArray(); } } public static byte[] Serialize(T obj) { return Serialize((Object)obj); } public static Object Deserialize(byte[] data, Type type) { MemoryStream ms = new MemoryStream(data); using (BsonReader reader = new BsonReader(ms)) { Object obj = _serializer.Deserialize(reader, type); return obj; } } public static T Deserialize(byte[] data) { return (T)Deserialize(data, typeof(T)); } } public class BsonUtcSerializer : JsonSerializer { private class DateTimeConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(DateTime) == objectType || typeof(DateTime?) == objectType; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var dateTimeOffset = (DateTime)value; // Serialize DateTimeOffset as round-trip formatted string serializer.Serialize(writer, dateTimeOffset.ToString("O")); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Date) return null; DateTime dt; var dateWithOffset = (String)reader.Value; if (String.IsNullOrEmpty(dateWithOffset)) return null; if (DateTime.TryParseExact(dateWithOffset, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt)) return dt; return null; } } private class DateTimeContractResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { var contract = base.CreateContract(objectType); if (objectType == typeof(DateTime) || objectType == typeof(DateTime?)) contract.Converter = new DateTimeConverter(); return contract; } } public BsonUtcSerializer() { ContractResolver = new DateTimeContractResolver(); DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; } } }