using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class StackConverter : JsonConverter
static Type StackParameterType(Type objectType)
while (objectType != null)
if (objectType.IsGenericType)
var genericType = objectType.GetGenericTypeDefinition();
if (genericType == typeof(Stack<>))
return objectType.GetGenericArguments()[0];
objectType = objectType.BaseType;
public override bool CanConvert(Type objectType)
return StackParameterType(objectType) != null;
object ReadJsonGeneric<T>(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
var list = serializer.Deserialize<List<T>>(reader);
var stack = existingValue as Stack<T> ?? (Stack<T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
for (int i = list.Count - 1; i >= 0; i--)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
var parameterType = StackParameterType(objectType);
var method = GetType().GetMethod("ReadJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
var genericMethod = method.MakeGenericMethod(new[] { parameterType });
return genericMethod.Invoke(this, new object[] { reader, objectType, existingValue, serializer });
catch (TargetInvocationException ex)
throw new JsonSerializationException("Failed to deserialize " + objectType, ex);
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
public string Name { get; set; }
readonly Stack<Card> cards = new Stack<Card>();
public Stack<Card> Cards { get { return cards; } }
public static void Test()
game.Cards.Push(new Card() { Name = "Whatever" });
game.Cards.Push(new Card() { Name = "Whatever2" });
var settings = new JsonSerializerSettings
Converters = { new StackConverter() },
string ser = JsonConvert.SerializeObject(game, settings);
var unser = JsonConvert.DeserializeObject<Game>(ser, settings);
var json2 = JsonConvert.SerializeObject(unser, settings);
Console.WriteLine(json2);
Assert.IsTrue(game.Cards.Select(c => c.Name).SequenceEqual(unser.Cards.Select(c => c.Name)));
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
public static void IsTrue(bool value, string message)
throw new AssertionFailedException(message ?? "failed");