我通过网络发送3个.net对象:
- List<int>
- List<ParentObject>
- string
这就是我序列化的方式(所有类型都相同):
JsonSerializerSettings JSsettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Arrays
};
string message = JsonConvert.SerializeObject(listOfParents, JSsettings);
//listOfParents is of type List<ParentObject>
ParentObject是一个抽象类,有两个子类。它有一个属性来获取它所代表的子类型。
public enum EntityType {Child1, Child2};
class ParentObject
{
public EntityType et { get; set; }
//..other members
}
我想根据收到的3个对象中的哪一个调用3个不同的函数。
Object genericObject = JsonConvert.DeserializeObject(message, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
if (genericObject is List<int>)
{
List<int> myList= (List<int>)genericObject;
myfunction1(myList);
}
if (genericObject is List<ParentObject>)
{
//etc..
ParentObject在DeserializeObject()中导致问题,因为它说“无法创建类型为ParentObject的实例.Type是一个接口或抽象类,无法实例化”。所以我想我可能需要在http://james.newtonking.com/projects/json/help/index.html?topic=html/CustomCreationConverter.htm
使用CustomCreationConverter由于CustomCreationConverter在反序列化期间需要类型,但我不会检查类型,直到 反序列化后才检查类型。
有任何解决问题的建议吗?
答案 0 :(得分:0)
如果我使用这样定义的对象:
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
方法即可,但您需要执行其他工作,因为此方法返回JContainer
,而不是object
。