我有一个要序列化的数据类,它包含派生类的 IEnumerable 属性,但将它们存储为它们的基类:
public class ToSerializeClass
{
public IEnumerable<BaseClass> DerivedClasses{ get; set; }
public ToSerializeClass ()
: base(ClassTypeEnum.TestClassType)
{
}
}
如果有帮助: ClassTypeEnum 枚举用于不同的目的,但如果有必要,它可以在以后识别派生类的类型,因为它被序列化(例如,如果我可以使用枚举字典和类型来解决我的问题)。
序列化成功完成,序列化类是所有预期派生类。所以,JSON字符串没问题。
问题是,当我尝试反序列化 ToSerializeClass 类的实例时,我必须为JavaScriptSerializer提供一个Type:
// sorry for the long names, trying to make it obvious
var deserialized = _serializer.Deserialize<BaseClass>(jsonStringOfIEnumerableBaseClasses);
由于我已将 BaseClass 作为Type提供,因此反序列化的结果是基类的集合,并且所有派生信息都将丢失。
如何反序列化 ToSerializeClass 实例以获得派生类的列表(IEnumerable)?
我可以完全控制源代码,所以我可以修改我的数据类,必要时使用不同的集合,但是如果可能的话我想用JavaScriptSerializer来解决它。
谢谢!
答案 0 :(得分:2)
您可以使用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" }
]
}