using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public enum SomeEnum { Value };
public string Value { get; set; }
public static void Test()
Test(new DateTime(2012, 1, 1));
Test((DateTime?)new DateTime(2012, 1, 1));
Test(new Version(1, 2, 3));
Test(new Model { Value = "Hello" });
Test(new [] { 1, 2, 3 });
Test(JToken.FromObject(new Model { Value = "Hello" }));
Test(JToken.FromObject(new [] { 1, 2, 3 }));
static void Test<T>(T obj)
Console.WriteLine("Testing {0}:", obj);
var json = JsonExtensions.Convert(obj);
var objBack = JsonExtensions.UnConvert<T>(json);
Assert.IsTrue((obj == null && objBack == null) || obj != null && objBack != null && obj.GetType() == objBack.GetType());
var jsonBack = JsonExtensions.Convert(objBack);
Assert.AreEqual(json, jsonBack);
public static partial class JsonExtensions
static readonly IContractResolver globalResolver = new JsonSerializer().ContractResolver;
public static string Convert<T>(T cacheObject)
return JsonConvert.SerializeObject(ToTypeWrapperIfRequired(cacheObject), Formatting.Indented, new JsonSerializerSettings
TypeNameHandling = TypeNameHandling.All
public static T UnConvert<T>(string json)
var obj = JsonConvert.DeserializeObject<object>(json, new JsonSerializerSettings
TypeNameHandling = TypeNameHandling.All
if ((obj is TypeWrapper wrapper))
return (T)wrapper.ObjectValue;
static object ToTypeWrapperIfRequired<T>(T obj, IContractResolver resolver = null)
resolver = resolver ?? globalResolver;
if (obj is bool || obj is string)
var contract = resolver.ResolveContract(obj.GetType());
if (contract is JsonPrimitiveContract)
return TypeWrapper.CreateWrapper(obj);
public abstract class TypeWrapper
protected TypeWrapper() { }
public abstract object ObjectValue { get; }
public static TypeWrapper CreateWrapper<T>(T value)
return new TypeWrapper<T>();
var type = value.GetType();
return new TypeWrapper<T>(value);
return (TypeWrapper)Activator.CreateInstance(typeof(TypeWrapper<>).MakeGenericType(type), value);
public sealed class TypeWrapper<T> : TypeWrapper
public TypeWrapper() : base() { }
public TypeWrapper(T value)
public override object ObjectValue { get { return Value; } }
public T Value { get; set; }
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];