Deserializing interface properties with Json.NET

Newtonsoft.json nuget package allows you to serialize and deserialize objects into json.

Install-Package Newtonsoft.Json

In this post I am going to show you how to handle a scenario where your models are structured after interfaces and you need to implement them, but then you also need to know what the concrete type is to be able to deserialize your json.

Some basic operations from Newtonsoft.Json are:

You can convert an object to Json using:

JsonConvert.SerializeObject(main);

And convert it back using:

YourType x = JsonConvert.DeserializeObject<YourType>(json);

It also supports dynamic objects

dynamic dyn = JsonConvert.DeserializeObject(json);
// dyn.Stuff

Those methods work just fine for concrete types, however if you have an interface in the middle you are going to get errors. For example, given the following structure:

public interface IMainStuff
{
    ISubStuff SubStuff { get; set; }
}
public interface ISubStuff
{
    string Name { get; set; }
}

public class MainStuff : IMainStuff
{
    public ISubStuff SubStuff { get; set; }
}

public class SubStuff : ISubStuff
{
    public string Name { get; set; }
}

If you attempt to deserialize MainStuff you are going to get the following exception:

An unhandled exception of type ‘Newtonsoft.Json.JsonSerializationException’ occurred in Newtonsoft.Json.dll

Additional information: Could not create an instance of type ConsoleApplication1.Program+ISubStuff. Type is an interface or abstract class and cannot be instantiated. Path ‘SubStuff.Name’, line 1, position 20.

Json.NET does not know how to create the interface. If you want to be able to handle it you have to implement a converter.

public class ConcreteConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override object ReadJson(JsonReader reader,
     Type objectType, object existingValue, JsonSerializer serializer)
    {
        return serializer.Deserialize<T>(reader);
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

And then tell your concrete class how to handle the interface property by annotating it with the converter information.

public class MainStuff : IMainStuff
{
    [JsonConverter(typeof(ConcreteConverter<SubStuff>))]
    public ISubStuff SubStuff { get; set; }
}

2015-14-18 07-14-37-003

Advertisements

4 thoughts on “Deserializing interface properties with Json.NET

    1. BrunoLM Post author

      You can have a converter that resolves objectType parameter in Read/Write methods.

      Example using MEF:

      Mef.Container.GetExports(objectType, null, null);
      

      Or something like that and use your custom logic to determine which concrete type it should take, then call:

      serializer.Deserialize(reader, yourConcreteType);
      
      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s