using System.Collections.Generic;
using System.Diagnostics;
using System.Collections;
using System.Runtime.Serialization;
using System.ComponentModel;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class TestConverter<TBaseType> : JsonConverter
static Stack<Type> typeStack;
static Stack<Type> TypeStack { get { return typeStack = (typeStack ?? new Stack<Type>()); } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
using (TypeStack.PushUsing(value.GetType()))
token = JToken.FromObject(value, serializer);
string[] omit = new string[] { "Name" };
JObject jObject = token as JObject;
foreach (JProperty property in jObject.Properties().Where(p => omit.Contains(p.Name, StringComparer.OrdinalIgnoreCase)).ToList())
public override bool CanConvert(Type objectType)
if (typeof(TBaseType).IsAssignableFrom(objectType))
return TypeStack.PeekOrDefault() != objectType;
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
throw new NotImplementedException();
public static class StackExtensions
public struct PushValue<T> : IDisposable
public PushValue(T value, Stack<T> stack)
#region IDisposable Members
public static T PeekOrDefault<T>(this Stack<T> stack)
throw new ArgumentNullException();
public static PushValue<T> PushUsing<T>(this Stack<T> stack, T value)
throw new ArgumentNullException();
return new PushValue<T>(value, stack);
public class ClassBaseType
public string Name { get; set; }
public class Class2 : ClassBaseType
public string Value { get; set; }
public class Class1 : ClassBaseType
public Class2 Value { get; set; }
public Class1 Class1 { get; set; }
public static void Test()
var test = new TestClass { Class1 = new Class1 { Name = "name", Value = new Class2 { Name = "foo", Value = "some string" } } };
var settings = new JsonSerializerSettings { Converters = new[] { new TestConverter<ClassBaseType>() } };
var defaultJson = JsonConvert.SerializeObject(test, Formatting.Indented);
var trimmedJson = JsonConvert.SerializeObject(test, Formatting.Indented, settings);
ConsoleAndDebug.WriteLine("\nDefault JSON serialization:");
ConsoleAndDebug.WriteLine(defaultJson);
ConsoleAndDebug.WriteLine("\nTrimmed JSON serialization:");
ConsoleAndDebug.WriteLine(trimmedJson);
if (JToken.Parse(trimmedJson).SelectTokens("..Name").Any())
throw new InvalidOperationException("JToken.Parse(trimmedJson).SelectTokens(\"..Name\").Any()");
public static class ConsoleAndDebug
public static void WriteLine(object s)
public static void Main()
Console.WriteLine(string.Format("Json.NET version: {0}.\n", typeof(JsonSerializer).Assembly.FullName));