JsonInheritanceConverter
Defines the class as inheritance base class and adds a discriminator property to the serialized object.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using NJsonSchema.Infrastructure;
using System;
using System.Linq;
namespace NJsonSchema.Converters
{
public class JsonInheritanceConverter : JsonConverter
{
internal static readonly string DefaultDiscriminatorName = "discriminator";
private readonly string _discriminator;
public override bool CanWrite => true;
public JsonInheritanceConverter()
{
_discriminator = DefaultDiscriminatorName;
}
public JsonInheritanceConverter(string discriminator)
{
_discriminator = discriminator;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JsonContract jsonContract = serializer.ContractResolver.ResolveContract(value.GetType());
jsonContract.Converter = null;
JObject jObject = JObject.FromObject(value, serializer);
jObject.AddFirst(new JProperty(_discriminator, value.GetType().Name));
writer.WriteToken(jObject.CreateReader());
jsonContract.Converter = this;
}
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = serializer.Deserialize<JObject>(reader);
string discriminator = jObject.GetValue(_discriminator).Value<string>();
Type objectSubtype = GetObjectSubtype(objectType, discriminator);
JsonContract jsonContract = serializer.ContractResolver.ResolveContract(objectSubtype);
jsonContract.Converter = null;
object result = serializer.Deserialize(jObject.CreateReader(), objectSubtype);
jsonContract.Converter = this;
return result;
}
private Type GetObjectSubtype(Type objectType, string discriminator)
{
dynamic val = (from a in ReflectionExtensions.GetCustomAttributes(objectType.GetTypeInfo(), true)
where a.GetType().Name == "KnownTypeAttribute"
select a).SingleOrDefault((Attribute a) => IsKnwonTypeTargetType(a, discriminator));
if (val != null)
return (Type)val.Type;
string name = objectType.Namespace + "." + discriminator;
return objectType.GetTypeInfo().Assembly.GetType(name);
}
private bool IsKnwonTypeTargetType(dynamic attribute, string discriminator)
{
return (byte)(attribute?.Type.Name == discriminator) != 0;
}
}
}