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?
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,
});
In my case, setting the TypeNameHandling
to Auto
didn't fix the problem, but setting it to All
fixed the issue. As the TypeNameHandling = TypeNameHandling.All
seemed a bit overkill to me, I chose Auto
again, but this time, I passed the type of my root object to the JsonConvert.SerializeObject
function as well:
var settings = new JsonSerializerSettings{ TypeNameHandling = TypeNameHandling.Auto };
var json = JsonConvert.SerializeObject(obj, typeof(ObjType), settings);
var deserializedObj = JsonConvert.DeserializeObject<ObjType>(json, settings);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With