using Newtonsoft.Json.Serialization;
public abstract class EventDataBase
public class AEventData : EventDataBase
public string A { get; private set; }
public AEventData(string a)
public class BEventData : EventDataBase
public string B { get; private set; }
public BEventData(string b)
public string Id { get; private set; }
public string Type { get; private set; }
public EventDataBase Data { get; private set; }
public Event(string id, string type, EventDataBase data)
public class CustomContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
var property = base.CreateProperty(member, memberSerialization);
if (member.DeclaringType == typeof(Event) && member.Name == "Type")
property.Order = Int32.MinValue;
property.MemberConverter = new EventTypeConverter();
else if (member.DeclaringType == typeof(Event) && member.Name == "Data")
property.Order = Int32.MaxValue;
property.MemberConverter = new EventDataConverter();
private class EventTypeConverter : JsonConverter
public override bool CanWrite { get { return false; } }
public override bool CanConvert(Type objectType)
return objectType == typeof(string);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var eventType = reader.Value as string;
serializer.ReferenceResolver.AddReference(serializer, "parentEvent.type", eventType);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
private class EventDataConverter : JsonConverter
public override bool CanWrite { get { return false; } }
public override bool CanConvert(Type objectType)
return objectType == typeof(EventDataBase);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var eventType = serializer.ReferenceResolver.ResolveReference(serializer, "parentEvent.type") as string;
var eventDataType = GetEventDataTypeFromEventType(eventType ?? "");
return serializer.Deserialize(reader, eventDataType);
private static Type GetEventDataTypeFromEventType(string eventType)
switch (eventType.ToLower())
return typeof(AEventData);
return typeof(BEventData);
throw new InvalidOperationException();
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
public static void Main()
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CustomContractResolver();
var eventA = JsonConvert.DeserializeObject<Event>(jsonEventA, settings);
var eventB = JsonConvert.DeserializeObject<Event>(jsonEventB, settings);
Console.WriteLine("{0} - {1}", eventA.Type, eventA.Data.GetType().Name);
Console.WriteLine("{0} - {1}", eventB.Type, eventB.Data.GetType().Name);