[英]Serialize multiple objects of different types with JSON
我有兩個從抽象類繼承的類
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.dll中發生類型'System.Runtime.Serialization.SerializationException'的異常,但未在用戶代碼中處理
附加信息:不需要使用數據協定名稱為“ Class1: http : //schemas.datacontract.org/2004/07/MyProject ”的“ MyProject.Class1”。 將任何靜態未知的類型添加到已知類型的列表中-例如,通過使用KnownTypeAttribute屬性或將它們添加到傳遞給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()]。 如果沒有,我將收到一個空字符串“ {}”的結果
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);
那么,如何序列化多個不同類型的對象?
我知道了。 唯一要做的就是僅在主基類上添加DataContract屬性
[DataContract()]
public class MainBaseClass {}
然后,在每個子類上,我們需要添加KnownType屬性
[KnownType(typeof(Class1))]
public class Class1 : MainBaseClass
{
}
[KnownType(typeof(Class2))]
public class Class2 : MainBaseClass
{
}
就是這樣! 那解決了我最初的問題。
如果要使用DataContractJsonSerializer
,則需要用KnownType
屬性修飾MainBaseClass
,以便在編譯時將所有可能的派生類型通知串行器。 在以下文檔中描述了此要求: 數據協定已知類型和此處: 獨立JSON序列化:多態
[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; }
}
這樣做之后,一個額外的JSON屬性“__type”將發射類型的多態領域MainBaseClass
與價值“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序列化 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.