Skip to content

Instantly share code, notes, and snippets.

@hediet
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hediet/3db87d8f39c22ffee9de to your computer and use it in GitHub Desktop.
Save hediet/3db87d8f39c22ffee9de to your computer and use it in GitHub Desktop.
CustomDiscriminatorObjectConverter
using System;
using System.Diagnostics.Contracts;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Hediet.Json.Converter
{
public class CustomDiscriminatorObjectConverter : Newtonsoft.Json.JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var discrimatorKey = GetDiscriminatorKey(objectType);
var obj = JObject.Load(reader);
var discriminator = obj[discrimatorKey].Value<string>();
obj.Remove(discrimatorKey);
var type = ResolveDiscriminator(objectType, discriminator);
return serializer.Deserialize(obj.CreateReader(), type);
}
protected virtual Type ResolveDiscriminator(Type type, string discriminator)
{
var attrs = type.GetCustomAttributes(typeof(DiscriminatedSubtypeAttribute), false).OfType<DiscriminatedSubtypeAttribute>();
var attr = attrs.FirstOrDefault(a => a.Discriminator == discriminator);
if (attr == null)
return null;
return attr.Type;
}
protected virtual string GetDiscriminatorKey(Type type)
{
var attr = type.GetCustomAttributes(typeof (DiscriminatedClassAttribute), false).OfType<DiscriminatedClassAttribute>().FirstOrDefault();
if (attr == null)
return null;
return attr.DiscriminatorKey;
}
public override bool CanConvert(Type objectType)
{
if (!objectType.IsClass && !objectType.IsInterface)
return false;
var d = GetDiscriminatorKey(objectType);
return d != null;
}
}
}
using System;
namespace Hediet.Json.Converter
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class DiscriminatedClassAttribute : Attribute
{
public string DiscriminatorKey { get; private set; }
public DiscriminatedClassAttribute(string discriminatorKey)
{
DiscriminatorKey = discriminatorKey;
}
}
}
using System;
namespace Hediet.Json.Converter
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class DiscriminatedSubtypeAttribute : Attribute
{
public string Discriminator { get; private set; }
public Type Type { get; private set; }
public DiscriminatedSubtypeAttribute(string discriminator, Type type)
{
Discriminator = discriminator;
Type = type;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment