Search code examples
c#json.net

Could not create an instance of type X. Type is an interface or abstract class and cannot be instantiated


Using version 7.0.1 Beta3, I'm trying to serialize/deserialize a complex POCO with properties that are arrays of abstract classes. These arrays could contain instance of classes that are derived from abstract ones.

At serialization, everything seems OK. The Json fragment below shows that the type information is set correctly.

The Json fragment:

 "Items": 
 [
     {
         "$type": "IVXB_TS, ...",
         "inclusive": true,
         "value": "20091231"
     }
 ]

But a deserialization it fails with the following error:

Could not create an instance of type QTY. Type is an interface or abstract class and cannot be instantiated.

The class hierarchy is the following :

[System.Xml.Serialization.XmlIncludeAttribute(typeof(IVXB_TS))]
public abstract partial class ANY : object, System.ComponentModel.INotifyPropertyChanged
{
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(IVXB_TS))]
public abstract partial class QTY : ANY
{
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(IVXB_TS))]
public partial class TS : QTY
{
}

public partial class IVXB_TS : TS
{
}

The Items property :

[System.Xml.Serialization.XmlElementAttribute("high", typeof(IVXB_TS))]
[System.Xml.Serialization.XmlElementAttribute("low", typeof(IVXB_TS))]
public QTY[] Items

The type information in the Json fragment seems to not be used. Is this a deserialization configuration issue?


Solution

  • The solution to this problem is to configure the deserializer to use the type information in the json. It is not used by default.

    Serialization is done this way:

    Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
    serializer.Converters.Add(new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter());
    serializer.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
    serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
    serializer.Formatting = Newtonsoft.Json.Formatting.Indented;
    
    using (StreamWriter sw = new StreamWriter(fileName))
    using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
    {
        serializer.Serialize(writer, obj, typeof(MyDocumentType));
    }
    

    At deserialization, the settings for TypeNameHandling must be set:

    MyDocumentType  obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MyDocumentType>(File.ReadAllText(fileName), new Newtonsoft.Json.JsonSerializerSettings 
    { 
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto,
        NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
    });