I went through the questions on the subject, and the closest to my situation didn't address my concern.
I have the following classes :
public abstract class BaseClass
{
}
public class ConcreteClass
{
}
My setting object for both the serialization and the deserialization is the following one :
JsonSerializerSettings _serializationSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.All,
ContractResolver = new CloudantContractResolver(),
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
I am trying to deserialize like this:
var myDeserializedObject = JsonConvert.DeserializeObject<BaseClass>(jsonString, _serializationSettings);
But for some reason, I am getting the error
Could not create an instance of type BaseClass. Type is an interface or abstract class and cannot be instantiated.
even though the root Json object does have a $type
property. I've tried deserializing to a JObject
and then using JObject.To<BaseType>()
, but I'm having the same result. I need to get this approach working, and would prefer not to use custom converters as I use polymorphism all over the place.
Do you have any idea on how I can get this deserialization working?
Update 10/10/15
I am still investigating, and I think that the issue might be that when I inspect the JObject
of my deserialized object, the first property is the _id
property:
I assume that since the error message is :
JSON.NET probably needs to read the type first to instantiate the correct object. I don't see how to reproduce this situation where _id
is first, from a separate project like the one provided below. I tried, a couple of combination, of nested complex properties, but I always have the $type
first. And it is probably why it works fine there.
I am trying to put together an override of CreateProperties
on my ContractResolver :
protected override System.Collections.Generic.IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
var propWithDollar = properties.Where(x => x.PropertyName.Contains("$"));
foreach (var prop in propWithDollar)
{
properties.Remove(prop);
properties.Insert(0, prop);
}
return properties;
}
But so far it has no effect on the order of my properties in the JObject
.
Update 2
Ok, so I managed to do put the $type
property at the very top by using :
var prop = deserializedJObject.Property("$type");
deserializedJObject.Remove("$type");
deserializedJObject.AddFirst(prop);
But unfortunately it didn't help, I'm still facing the same cast issue.
Update 3
I have been able to reproduce the issue. If the $type
property is not the very first property in the JSON string then this error occurs. This is clearly a bug, as the JSON specification indicates that the properties are unordered.
In my situation I don't quite have much control over that, as the JSON object is returned by a database that always puts _id
at the top. I'll log an issue on GitHub and see if I can come up with a workaround.
Here is a project that reproduces the issue : http://we.tl/RiemGkRTF2