Solution for deserialization is to build a CustomConverter:
public class BaseClassJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(BaseClass) == objectType;
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
try
{
var jObject = JObject.Load(reader);
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new BaseClassJsonConverter());
if (jObject.ContainsKey("Foo"))
return JsonConvert.DeserializeObject<Leaf>(jObject.ToString(), jsonSerializerSettings);
else if (jObject.ContainsKey("ClassList"))
return JsonConvert.DeserializeObject<Composite>(jObject.ToString(), jsonSerializerSettings);
else
throw new System.SystemException("Class not implemented");
return null;
}
catch (JsonReaderException)
{
return null;
}
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Key difference to other answers I found is that they were missing to put the settings in the ReadJson into the SeserialzieObject
again, that way it couldn't handle the deserialization of a recursive structure (Deserializing JSON to abstract class).
Now you either decorate your BaseClass with: [JsonConverter(typeof(BaseConverter))]
Or you call the deserialization with the converter in the settings:
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new BaseClassJsonConverter());
JsonConvert.DeserializeObject<BaseClass>(jsonString, jsonSerializerSettings);