使用JavascriptSerializer将基类的IEnumerable反序列化为派生类
本文关键字:反序列化 派生 IEnumerable JavascriptSerializer 基类 使用 | 更新日期: 2023-09-27 18:22:08
我有一个要序列化的数据类,它包含派生类的IEnumerable属性,但将它们存储为它们的基类:
public class ToSerializeClass
{
public IEnumerable<BaseClass> DerivedClasses{ get; set; }
public ToSerializeClass ()
: base(ClassTypeEnum.TestClassType)
{
}
}
如果有帮助的话:ClassTypeEnum枚举有不同的用途,但如果必要,它可以在以后识别派生类的类型,因为它是序列化的(例如,如果我可以使用枚举和类型的字典来解决我的问题)。
序列化成功完成,并且序列化的类都是预期的派生类。所以,JSON字符串是可以的。
问题是,当我试图反序列化ToSerializeClass类的实例时,我必须为JavaScriptSerializer:提供一个类型
// sorry for the long names, trying to make it obvious
var deserialized = _serializer.Deserialize<BaseClass>(jsonStringOfIEnumerableBaseClasses);
由于我提供了BaseClass作为Type,因此反序列化的结果是基类的集合,并且所有派生信息都将丢失。
如何反序列化ToSerializeClass实例以获得派生类的列表(IEnumerable)?
我对源代码有完全的控制权,所以我可以修改我的数据类,在必要时使用不同的集合,但如果可能的话,我想使用JavaScriptSerializer来解决它。
谢谢!
您可以使用SimpleTypeResolver将类型信息嵌入到序列化的JSON中。
例如:
void Main()
{
JavaScriptSerializer serializer = new JavaScriptSerializer(new SimpleTypeResolver());
var original = new Container()
{
List = new List<A> { new A(), new B(), new C() }
};
var json = serializer.Serialize(original);
var deserialized = serializer.Deserialize<Container>(json);
Console.WriteLine(deserialized.List[0].GetType() == typeof(A)); // true
Console.WriteLine(deserialized.List[1].GetType() == typeof(B)); // true
Console.WriteLine(deserialized.List[2].GetType() == typeof(C)); // true
}
public class Container
{
public IList<A> List
{ get; set; }
}
public class A
{ }
public class B : A
{ }
public class C : A
{ }
请注意,JSON增加了__type
成员,这些成员包含类型的完全限定名称。因此JSON变得有些难看,例如在我的情况下(通过LINQPad运行它):
{
"__type": "UserQuery+Container, query_cxbxwu, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"List": [
{ "__type": "UserQuery+A, query_cxbxwu, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" },
{ "__type": "UserQuery+B, query_cxbxwu, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" },
{ "__type": "UserQuery+C, query_cxbxwu, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" }
]
}
当然,您也可以推出自己的JavaScriptTypeResolver,这可能会让它变得更漂亮。
例如,一个非常简单(但也不是很好)的实现可以只使用直接的类名:
public class MyTypeResolver : JavaScriptTypeResolver
{
public override Type ResolveType(string id)
{
return typeof(MyTypeResolver).Assembly.GetTypes().First(t => t.Name == id);
}
public override string ResolveTypeId(Type type)
{
return type.Name;
}
}
由此产生的JSON会简单得多:
{
"__type": "Container",
"List": [
{ "__type": "A" },
{ "__type": "B" },
{ "__type": "C" }
]
}