我有两个继承自抽象类的类
public class Class1 : MainBaseClass
{
public int attrib1 {get; set;}
public int attrib2 {get; set;}
}
public class Class2 : MainBaseClass
{
public int attribx {get; set;}
public int attriby {get; set;}
}
然后我创建了一个MainBaseClass类型的列表,以便在一个JSON字符串中序列化这两个类但是我得到了这个异常
类型的例外 ' System.Runtime.Serialization.SerializationException'发生在 System.Runtime.Serialization.dll但未在用户代码中处理
其他信息:键入' MyProject.Class1'与数据合同 名称'第1类:http://schemas.datacontract.org/2004/07/MyProject'不是 预期。将任何静态未知的类型添加到已知列表中 types - 例如,通过使用KnownTypeAttribute属性或by 将它们添加到传递给的已知类型列表中 DataContractSerializer的。
我的方法是这样做的:
Class1 class1 = getData();
Class2 class2 = getData();
Package<MainBaseClass> package = new Package<MainBaseClass>();
package.AddObject(class1)
package.AddObject(class2);
//Here's the error
new ServiceClass().Serialize<Package<MainBaseClass>>(package);
我的包类
public class Package<T>
{
public List<T> Objects = new List<T>();
public Package() { }
public void AddObject(T dto)
{
this.Objects.Add(dto);
}
}
我的序列化方法
public static string Serialize<T>(T entity)
{
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
//Here's the exception
ser.WriteObject(stream, entity);
stream.Position = 0;
StreamReader sr = new StreamReader(stream);
return sr.ReadToEnd();
}
我还在MainBaseClass上添加了[DataContract()],子类和异常仍然存在。
只有在我这样做的情况下才能工作,之前从基类和子类中删除[DataContract()]。如果没有,我会将结果作为空字符串&#34; {}&#34;
收到Class1 class1 = getData();
Package<Class1> package = new Package<Class1>();
package.AddObject(class1)
string str = new ServiceClass().Serialize<Package<Class>>(package);
或者这个:
Class1 class1 = getData();
string str = new ServiceClass().Serialize<Class1>(class1);
那么,我如何序列化不同类型的多个对象?
答案 0 :(得分:2)
我明白了。唯一要做的就是只在主基类上添加DataContract属性
[DataContract()]
public class MainBaseClass {}
然后,在每个子类上,我们需要添加KnownType属性
[KnownType(typeof(Class1))]
public class Class1 : MainBaseClass
{
}
[KnownType(typeof(Class2))]
public class Class2 : MainBaseClass
{
}
那就是它!这解决了我最初的问题。
答案 1 :(得分:2)
如果您要使用DataContractJsonSerializer
,则需要使用KnownType
属性修饰MainBaseClass
,以便在编译时通知序列化程序所有可能的派生类型 。此处的文档中描述了此要求:Data Contract Known Types和此处:Stand-Alone JSON Serialization: Polymorphism
[DataContract]
[KnownType(typeof(Class1))]
[KnownType(typeof(Class2))]
public abstract class MainBaseClass
{
[DataMember]
public int Id { get; set; } // For instance.
}
[DataContract]
public class Class1 : MainBaseClass
{
[DataMember]
public int attrib1 { get; set; }
[DataMember]
public int attrib2 { get; set; }
}
[DataContract]
public class Class2 : MainBaseClass
{
[DataMember]
public int attribx { get; set; }
[DataMember]
public int attriby { get; set; }
}
完成此操作后,将为类型为MainBaseClass
的多态字段发出额外的JSON属性“__type”,其值为“DataContractName:DataContractNamespace”。此语法是JSON标准的.Net扩展,并提供了一个提示,以便在反序列化时使用哪种具体类型。因此,如果您的Package
课程如下:
[DataContract]
public class Package<T>
{
[DataMember]
public List<T> Objects = new List<T>();
public Package() { }
public void AddObject(T dto)
{
this.Objects.Add(dto);
}
}
发出的JSON将如下所示:
{"Objects":[{"__type":"Class1:#Tile.Question28612192","Id":101,"attrib1":1,"attrib2":2},{"__type":"Class2:#Tile.Question28612192","Id":-101,"attribx":-1,"attriby":-2}]}
如果您不想这样,在.Net 4.5及更高版本中,可以通过将DataContractJsonSerializerSettings.EmitTypeInformation
设置为EmitTypeInformation.Never
来抑制DataContractJsonSerializer
类型信息的输出:
var settings = new DataContractJsonSerializerSettings { EmitTypeInformation = EmitTypeInformation.Never };
但是,如果没有类型信息,您将无法在DataContractJsonSerializer
之后反序列化您的JSON。
作为替代方案,您可以考虑使用Json.NET,它不需要预先了解所有可能的派生类型以进行序列化。有关详细信息,请参见此处:JSON serialization of array with polymorphic objects。