无法创建类型X的实例.Type是接口或抽象类,无法实例化

时间:2015-05-20 12:29:52

标签: c# json.net

使用版本7.0.1 Beta3,我正在尝试使用属于抽象类数组的属性序列化/反序列化复杂的POCO。这些数组可以包含派生自抽象类的实例。

在序列化时,一切似乎都没问题。下面的Json片段显示正确设置了类型信息。

Json片段:

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

但是反序列化失败并出现以下错误:

无法创建QTY类型的实例。 Type是接口或抽象类,无法实例化。

类层次结构如下:

[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
{
}

Items属性:

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

似乎没有使用Json片段中的类型信息。这是反序列化配置问题吗?

2 个答案:

答案 0 :(得分:15)

此问题的解决方案是将反序列化器配置为使用json 中的类型信息。默认情况下不使用它。

序列化以这种方式完成:

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));
}

在反序列化时,必须设置TypeNameHandling的设置:

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

答案 1 :(得分:3)

就我而言,将 TypeNameHandling 设置为 Auto 并不能解决问题,但将其设置为 All 可以解决问题。由于 TypeNameHandling = TypeNameHandling.Auto 对我来说似乎有点矫枉过正,我再次选择了 Auto,但这一次,我也将根对象的类型传递给了 JsonConvert.SerializeObject 函数:

var settings = new JsonSerializerSettings{ TypeNameHandling = TypeNameHandling.Auto };

var json = JsonConvert.SerializeObject(obj, typeof(ObjType), settings);

var deserializedObj = JsonConvert.DeserializeObject<ObjType>(json, settings);