The Problem
Let’s say that you have a simple class structure such as this one:
public class Thing { public string Name { get; set; } } public class ThingContainer { public Thing TheThing { get; set; } }
Here we have a class ThingContainer
that has a single reference property of type Thing
, and Json.Net will do a great job of serializing and deserializing instances of ThingContainer
without any extra help:
static void Main(string[] args) { var container = new ThingContainer { TheThing = new Thing { Name = "something" } }; var serialized = JsonConvert.SerializeObject(container, Formatting.Indented); Console.WriteLine(serialized); // { // "TheThing": { // "Name: "something" // } // } var deserialized = JsonConvert.DeserializeObject<ThingContainer>(serialized); Console.WriteLine(deserialized.TheThing.Name); // "something" }
Unfortunately the real-world is rarely that simple and today you are writing a good model so you can’t go about using concrete types. Instead, you want to specify your properties as interfaces:
public interface IThing { string Name { get; set; } } public class Thing : IThing { public string Name { get; set; } } public class ThingContainer { //notice that the property is now of an interface type... public IThing TheThing { get; set; } }
After making these changes the serialization will still work as before, but when we try to deserialize the model we get the following error:
Could not create an instance of type JsonSerialization.IThing. Type is an interface or abstract class and cannot be instantated
This means that the JSON deserializer has seen that there is a property of type IThing
but doesn’t know what type of object it should create to populate it.
Enter JsonConverter
The solution to this is to explicitly tell the deserializer what type it should be instantiating, and we do this using an attribute – specifically the JsonConverterAttribute
.
The JsonConverterAttribute
is part of Json.Net, and allows you to specify a custom converter to handle serialization and deserialization of an object by extending JsonConverter
.
public class ThingContainer { [JsonConverter(typeof(/*CustomConverterType*/))] public IThing TheThing { get; set; } }
In this case we are going to write a custom implementation of JsonConverter
that will behave exactly as the non-attributed property would, but using a specific type.
The code below shows the shell of the converter class and the methods we need to override. Notice that we are specifying a generic type parameter TConcrete
on the class – this will set the desired concrete type for the property when we actually use the attribute later.
public class ConcreteTypeConverter<TConcrete> : JsonConverter { public override bool CanConvert(Type objectType) { //determine whether or not this converted can create an instance of //the specified object type } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //deserialize an object from the specified reader } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { //serialize the object value } }
The roles of the missing methods are fairly self explanatory, and seeing as we’re feeling lazy today we’ll pick off the easy ones first.
CanConvert
What we should be doing in CanConvert
is determining whether or not the converter can create values of the specified objectType
. What I am actually going to do here is just return true
(i.e. “yes, we can create anything”). This will get us through the example and leaves the real implementation as an exercise for the reader…
WriteJson
The WriteJson
method is responsible for serializing the object, and (as I mentioned above) the serialization of interface properties already works as expected. We can therefore just use the default serialization to fulfil our needs:
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { //use the default serialization - it works fine serializer.Serialize(writer, value); }
ReadJson
The ReadJson
method is where it starts to get interesting, as this is actually what is causing us the problem.
We need to re-implement this method so that it both instantiates and populates an instance of our concrete type.
Thankfully, Json.Net already knows how to populate the object – and any sub-objects, for that matter – so all we really need to do is get it to use the correct concrete type. We can do this by explicitly calling the Deserialize<T>
overload on the serializer:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //explicitly specify the concrete type we want to create //that was set as a generic parameter on this class return serializer.Deserialize<TConcrete>(reader); }
Usage and Final Code
Now that we have our custom attribute we just need to specify it on the model…
public class ThingContainer { [JsonConverter(typeof(ConcreteTypeConverter<Thing>))] public IThing TheThing { get; set; } }
…and we can deserialize without any errors!
The final code for the converter is below. There are quite a few extensions that could be made to this, but as a quick-fix to a problem that I come across often this will do the job nicely.
public class ConcreteTypeConverter<TConcrete> : JsonConverter { public override bool CanConvert(Type objectType) { //assume we can convert to anything for now return true; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //explicitly specify the concrete type we want to create return serializer.Deserialize<TConcrete>(reader); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { //use the default serialization - it works fine serializer.Serialize(writer, value); } }
Thanks for the post. Your solution does not work for multiple implementations of IThing. Which is the whole point of having an interface.
Do you have any solutions for multiple implementations of IThink? I think a better solution would be to serialize the type name (ie, Thing1, Thing2) so the deserializer knows what to do.
Suggestions?
Ryan
I would argue that having multiple implementations is neither the only nor the major purpose of interfaces. Interfaces define behavior to the outside world, an implementing class provides it. I have many examples of interfaces with only a single implementation in our project(s) and there are no plans for more, either. Interfaces keep your code where it belongs and avoids other classes messing with – or even relying on – some concrete way of implementing certain behavior. For that matter, the provided solution is very useful in many situations (at least for us).
If you know in your deserialization, which class you want to use to instantiate a member of a certain interface, you could do that by extending the given example providing both the types of the interface and the concrete class to the custom converter. Another approach has been proposed on stackoverflow in this answer: http://stackoverflow.com/a/8031283/177710, where the deserializer decides which type to instantiate based on the fields found in the currently parsed json snippet. Very interesting approach and answer!
This works great. Simply use the same JsonSerializerSettings on serialize & deserialize to use embedded type names.
// Serializer Settings
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
ObjectCreationHandling = ObjectCreationHandling.Auto
};
// Serialize
var json = JsonConvert.SerializeObject(tree, settings);
// Deserialize
var tree2 = JsonConvert.DeserializeObject(json, settings);
Hi Ryan. You’re right – this won’t work for multiple instances of IThing (though you could extend it to do so if you have consistent logic for selecting which Implementation to use) and I would definitely use the TypeNameHandling in that scenario as you suggest. This is more for those situations where you re either using an interface instead of a concrete type for better abstraction/test ability, and where you don’t have control over the JSON being deserialized.
Hi Steve, thanks for an insightful post and for linking to it on stackoverflow 🙂
Just wanted add that the CanConvert() method of the JsonConverter base class won’t be called when using the JsonConverterAttribute to provide a concrete implementation for a given member. Looks like that method will only be called when adding an instance to the Converters collection of a JsonSerializer instance that can be passed to the DeserializeObject() method. This makes sense, since in that latter scenario the deserializer doesn’t know yet which members it should apply the custom converter to.
Hi Oliver, glad you like it!
Thank you very much for the solution, we use Interfaces as part of a DDD approach so this is a great solution for deserializing. One question: If I put this attribute on an Interface declaration directly (rather than on a property of another class) then the JsonConverter gets into an infinite loop. Anyway around that?
Why are you putting it on the interface – doesn’t that destroy the benefits of programming to an interface? Now your interface has to know about every possible implementation, rather than being a common independent item.
can you explain how the Deserialzing knows which property it is converting from Interface to Concrete class,
[JsonConverter(typeof(ConcreteTypeConverter))]
ILanguage language {get;set;}
how does it know to convert the ILanguage interface into the concrete class Language?
You specify the concrete type as a generic type parameter of ConcreteTypeConverter
e.g. ConcreteTypeConverter
explain how it knows ILanguage is converted to Language, how does it map?
You explicitly specify Language as a parameter of the attribute. Language has to implement ILanguage
The bellow declaration does not work as is. How do you deal with complex types like “Dictionary” ? Thanks!
[JsonConverter(typeof(ConcreteTypeConverter<Dictionary>))]
public Dictionary Things{ get; set; }
The bellow does not work. How do you deal with complex types like “Dictionary” ?
public class ThingContainer
{
[JsonConverter(typeof(ConcreteTypeConverter<Dictionary>))]
public Dictionary TheThing { get; set; }
}
Can’t check right now but I’m pretty certain this works with dictionary types
This does not work for me.
public class ThingContainer
{
[JsonConverter(typeof(ConcreteTypeConverter<Dictionary))]
public Dictionary TheThing { get; set; }
}
Well written post. This fit our needs great and is my personal favorite of the several implementations I found. Great use of generics!
Yeah yeah yeah, this works. But it doesn’t work with Lists. You see, I have one property like this:
[JsonConverter(typeof(ConcreteTypeConverter<List>))]
public List CareChains { get; set; }
This doesn’t work. It says it can’t
‘Could not create an instance of type xxx…DomainModel.ICareNeed. Type is an interface or abstract class and cannot be instantiated.
`ConcreteTypeConverter` is meant to give Json.NET a hint as to what type to construct when the type information is insufficient. That’s actually not required for your `CareChains` property because it already has a concrete type defined: `List`.
I guess that what you’re looking to do is to provide a hint as to how the items _in_ the list should be created?
Somehow the copypaste made weird mess, or at the copying moment I had some changes that weren’t supposed to be there. This is how to property looks like:
[JsonConverter(typeof(ConcreteTypeConverter<List>))]
public List CareChains { get; set; }
Ok it made it again wtf..
again.. like this..
[JsonConverter(typeof(ConcreteTypeConverter<List >))]
public List CareChains { get; set; }
nooo.. this is not happening
[JsonConverter(typeof(ConcreteTypeConverter))]
public List^ICareChain^ CareChains { get; set; }
[JsonConverter(typeof(ConcreteTypeConverter^List^CareChain^^))]
public List^ICareChain^ CareChains { get; set; }
That’s ok, I get what you mean. You can still do this with a custom converter; you need to tell Json.NET how to serialise each item in the list instead of the list itself.
I know, but this code won’t do it. I guess I have to figure it out myself
Were you able to figure out how to do this conversion for a list of type? I’m looking for a solution for the same.
Did you figure out how to convert a List of a Type? I am looking for this solution as well.
Actually I did. I can check this today at work if I hopefully remember.
What happens when you have more implementors of IThing?
In my case, I have 2 classes derived from an abstract class, that I need to deserialize.
In that case you’ll need to provide some custom logic to determine which concrete type to instantiate.
What happens when you have more implementors of IThing?
In my case, I have 2 classes derived from an abstract class, that I need to deserialize.