物件迴圈引用與序列化問題

2021-07-27 08:30:22 字數 1444 閱讀 2765

最近遇到乙個問題,由於乙個物件內部存在相互引用,導致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...