最近遇到乙個問題,由於乙個物件內部存在相互引用,導致json序列化失敗.比如定義有乙個類有
class circlereference
public
void
setparam(string param)
public circlereference getreference()
public
void
setreference(circlereference reference)
public
static
void
main(string args)
那麼在main
方法中會拋stackoverflowerror.原因呢,就是在序列屬性reference
的時候,對同乙個物件,不停的遞迴,沒有結束,用盡棧空間,最終失敗.
於是,就思考了不同的序列化方案對迴圈引用是如何處理的.
會不同的進行遞迴,直到棧空間溢位,最終序列化失敗.
採用ide直接生成的tostring()方法,不停遞迴,最終棧溢位
hessian 序列化後的二進位制檔案中,有專門的一種引 用型別,在序列化的時候,對於每乙個object型別例項,都會放到乙個identityhashmap
中. 當下次發現有相同的例項時,就會直接寫乙個引用即可.反序列化時,亦同,沒有問題.
同hessian,也是有相應的引用型別.不會導致問題
protobuf在序列化時,我們一般是這樣用的
message.builder builder= message.newbuilder;
builder.setbuilder(builder);
message message = builder.build();
byte data = message.tobytearray();
因為乙個builder在經過build()以後,這個變數將不會再變化,因此在builder.set(builder)後,設定的那個builder在內部被build一次,生成乙個例項,這個例項的builder屬性為空.而後者在呼叫builder.build()的時候,又會生成另外乙個builder,這個builder和剛才設定在builder內部的builder不是同乙個builder,因此也不會有迴圈引用的問題.
因此,有這麼幾點規律
不是所有用於序列化的物件都可以迴圈引用: 如protobuf無何如何,你都做不到迴圈引用.因為,每次生成成的物件是不一樣的.
支援對迴圈引用序列化方案的需要滿足以下兩點
序列化後的資料型別有引用型別: 如果沒有引用型別,在序列化時,不能終止,在反序列化時,兩次處理的物件不確定是否是同乙個物件.
支援迴圈引用的序列化方案,應該是存在於同一種語言中:不同的語言,其引用可能會導致不一致,因為有些語言本身可能就不存在迴圈引用問題,比如c語言.
Wcf序列化的迴圈引用問題1
1.wcf資料契約序列化,使用的類datacontractserializer 預設如果類不指定 datacontract 則序列化類的所有字段,並且在出現迴圈引用的時候回丟擲異常,服務終止 msdn文件說明 wcf 資料契約序列化使用 datacontractserializer 底層是xml序列...
物件序列化與反序列化
using system using system.text using system.collections.generic using system.io using system.runtime.serialization.formatters.binary class serializabl...
物件序列化與反序列化
我們常常需要將一些程式當前資訊儲存在檔案中,如果明文儲存,那麼資訊不安全,使用物件序列化和反序列化可解決此問題 1 將需要儲存的資訊封裝成類,用serializable標記 serializable 次標記必須,以宣告此student類可執行序列化操作 class student public st...