如果我使用这样定义的对象:
public enum EntityType { Child1, Child2 };
abstract class ParentObject
{
public EntityType et { get; set; }
}
class ChildClass : ParentObject
{
public int ChildClassProp { get; set; }
public ChildClass()
{
this.et = EntityType.Child1;
}
}
class ChildClass2 : ParentObject
{
public int ChildClass2Prop { get; set; }
public ChildClass2()
{
this.et = EntityType.Child2;
}
}
然后我可以愉快地将派生类(ChildClass和ChildClass2)反序列化为ParentObject:
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects
};
List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });
string message = JsonConvert.SerializeObject(list,
Newtonsoft.Json.Formatting.Indented, JSsettings);
list = JsonConvert.DeserializeObject<List<ParentObject>>(message, JSsettings);
哪里message看起来像这样:
[
{
"$type": "ConsoleApplication4.ChildClass, ConsoleApplication4",
"ChildClassProp": 1,
"et": 0
},
{
"$type": "ConsoleApplication4.ChildClass2, ConsoleApplication4",
"ChildClass2Prop": 2,
"et": 1
}
]
这个关键是TypeNameHandling = TypeNameHandling.Auto同时用于序列化和反序列化。使用TypeNameHandling.Arrays会创建如下所示的消息:
{
"$type": "System.Collections.Generic.List`1[[ConsoleApplication4.ParentObject, ConsoleApplication4]], mscorlib",
"$values": [
{
"ChildClassProp": 1,
"et": 0
},
{
"ChildClass2Prop": 2,
"et": 1
}
]
}
请注意,不包括列表项的类型,仅包括列表的类型,因此您得到的错误。
编辑:
我认为让这个工作以你想要的方式工作的最简单方法是定义一个像这样的简单类,它充当你正在序列化的对象的薄包装器:
class ObjectContainer
{
public object Data { get; set; }
}
然后代码将如下所示(注意对 的更改TypeNameHandling.Auto):
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
};
List<ParentObject> list = new List<ParentObject>();
list.Add(new ChildClass() { ChildClassProp = 1 });
list.Add(new ChildClass2() { ChildClass2Prop = 2 });
ObjectContainer container = new ObjectContainer()
{
Data = list
};
string message = JsonConvert.SerializeObject(container,
Newtonsoft.Json.Formatting.Indented, JSsettings);
var objectContainer = JsonConvert.DeserializeObject<ObjectContainer>(message, JSsettings);
if (objectContainer.Data is List<int>)
{
Console.Write("objectContainer.Data is List<int>");
}
else if (objectContainer.Data is List<ParentObject>)
{
Console.Write("objectContainer.Data is List<ParentObject>");
}
else if (objectContainer.Data is string)
{
Console.Write("objectContainer.Data is string");
}
我采用这种方法的原因是 Json.Net 将负责几乎所有的工作。简单地调用非泛型JsonConvert.DeserializeObject方法就可以了,但是你需要做额外的工作,因为这个方法返回的是 a JContainer,而不是 a object。