alibaba fastjson的使用總結和心得

2022-09-11 15:30:35 字數 4601 閱讀 4486

最初接觸alibaba fastjson是由於其效能上的優勢,對比原來採用codehause.jackson的解析,在hadoop平台上的手動轉換物件有著將近1/3的效能提公升,但隨著開發應用越來越多,漸漸地也發現了在其他方面的強大之處,例如直接轉化泛型(jackson對泛型的支援相對來說就比較差)。

fastjson會自動處理物件中的泛型,將其解析成原來定義好的物件,建議一定要將泛型型別定義精確,以避免出現歧義,例如如果使用map就並不是乙個定義良好的泛型,我們也並不知道object物件真正表示的是什麼,而fastjson解析object時,由於不知道其具體型別,只能將其轉化成jsonobject(結構類似乙個map,有著key和value)。

如果頂層型別中存在泛型,就會出現不知道確切型別的狀況,因為class是無法攜帶泛型資訊的,j**a中不存在乙個型別為list.class,如果這樣使用,fastjson會將物件解析成jsonobject。

alibaba fastjson提供了一套typereference相關的方法來解決這個問題,從源**來看定義不是很長:

public class typereference

public type gettype()

public final static type list_string = new typereference>() {}.gettype();

}

建構函式中做了兩件事,先從當前的class.getgenericsuperclass,返回該class表示的實體或直接超類的type,重點在與,如果是引數化型別,返回的type中會帶上該型別,我們看一下這個方法的定義及其作用:

public typegetgenericsuperclass()
返回表示此 class 所表示的實體(類、介面、基本型別或 void)的直接超類的 type。

如果超類是引數化型別,則返回的 type 物件必須準確反映源**中所使用的實際型別引數。如果以前未曾建立表示超類的引數化型別,則建立這個型別。有關引數化型別建立過程的語義,請參閱parameterizedtype宣告。如果此 class 表示 object 類、介面、基本型別或 void,則返回 null。如果此物件表示乙個陣列類,則返回表示 object 類的 class 物件。

返回:

此物件所表示的類的超類

丟擲:

genericsignatureformaterror- 如果常規類簽名不符合 j**a virtual machine specification, 3rd edition 規定的格式

typenotpresentexception- 如果常規超類引用不存在的型別宣告

malformedparameterizedtypeexception- 如果常規超類引用的引數化型別由於某種原因無法例項化

從以下版本開始:

1.5從文件中可以看出,如果其超類是引數化型別,返回的type就為sun.reflect.generics.reflectiveobjects.parameterizedtypeimpl型別,其繼承自j**a.lang.reflect.parameterizedtype,用來表示引數化型別。

引數化型別中就可以從getactualtypearguments中獲取,因為typereference只有乙個引數化型別定義,因此可以確定返回的陣列肯定有乙個元素(如果是map就存在兩個元素),這樣type就為其引數化型別了,我們通過這個定義將物件的泛型傳入至後續的json處理邏輯中。

typegetactualtypearguments()
返回表示此型別實際型別引數的 type 物件的陣列。

注意,在某些情況下,返回的陣列為空。如果此型別表示巢狀在引數化型別中的非引數化型別,則會發生這種情況。

返回:

表示此型別的實際型別引數的 type 物件的陣列

丟擲:

typenotpresentexception- 如果任何實際型別引數引用不存在的型別宣告

malformedparameterizedtypeexception- 如果任何實際型別引數引用引數化型別,該型別出於某種原因無法被例項化

從以下版本開始:

1.5所以使用該類的方法只有一種,就是繼承,因此其構造方法為protected,只能允許子類來呼叫,在構造該物件時,就需要在宣告最後加上{}來表示繼承關係。

j**a.util.map
如果是陣列,由於某種物件的陣列是存在對應的class型別資訊的,也就是說可以直接直接以class的方式轉換成功。

當時如果沒有指定型別,就會轉換成jsonobject,在其中以key/value的方式(類似map)儲存。

如果是陣列,轉成jsonarray,在其中包裝jsonobject

如果我們使用typereference,指定其為list,而list中其實是物件,那麼直接轉換成string,此時字串就為json字串。

如果事先不知道該json串的型別資訊(json事先也無法知道其型別資訊,而j**a的序列化,是帶型別資訊的,因此攜帶的內容也要比json串豐富地多,耗費網路頻寬也大),或者在map中寫不出統一的泛型,那麼就會發生隱性的型別轉換過程。在codehaus jackson中會將無法識別的json物件直接轉換成map(key,value)格式,如果是fastjson,則轉換成jsonobject(其實也類似於json)。如果需要將該物件仍然轉換成json格式,不會有任何問題,但如果想要以原來的物件方式操作它,就會出現問題了(因為沒有物件資訊,除非手動將其轉換,但每部分都需要手寫**,比較麻煩)。

map中字段為null不被持久化的問題

如果map中的某個屬性為null,並不會被持久化,可以參考

如果想讓map中的字段能夠正常輸出(這也是我們需要的),就需要在轉換tojsonstring時設定特殊的feature來完成該功能:

json.tojsonstring(object, serializerfeature.writemapnullvalue)
參考:

fastjson中存在多種serializerfeature,可以按照需要使用,例如

很多場景中,我們需要序列化的物件中存在迴圈引用,在許多的json庫中,這會導致stackoverflow。在功能強大的fastjson中,你不需要擔心這個問題。

使用@jsonfield annotation來定製化序列化欄位的名稱,還可以使用@jsoncreator來指定建構函式來建立物件,配合@jsonfield來確定欄位的名稱。

如果使用新特性serializerfeature.writeclassname,可以在序列化的文字中加入@type資訊,這樣就可以進行合理的反序列化,因為知道了型別資訊,可以通過預設的構造以及屬性名稱自動設定,此時反序列化的結果類似下面:

此時就可以進行自動識別,但此時輸出的文字就會多出一倍的空間,因此如果有著明確的型別,不建議使用這種方式。

string text = ...; // 

color color = (color) json.parse(text);

這樣可以解決一些序列化泛型中介面的問題,

還舉例說明了可以使用組合型別,fastjson對這種結構的反序列化有專門支援:

string text = ...; // [, ]

type types = new type ;

listlist = json.parsearray(text, types);

header header = (header) list.get(0);

body body = (body) list.get(1);

在使用writeclassname這個feature來進行寫map等操作時,有乙個問題,其中的list以及陣列在被轉化回來時無法識別,會被自動轉換成jsonarray而不是原始的list,陣列物件。如果使用者原來使用的list,這個問題可以得到完美的解決,看一下jsonarray的定義,

/**

* @author wenshao[[email protected]]

*/public class jsonarray extends json implements list, cloneable, randomaccess, serializable {

可以對其進行強制轉換list即可。

但是如果原始型別為陣列型別,則只能夠通過toarray方法,至於網友提出的能否直接使用object,其開發者給出了預期(只不過在1.2.9上也並未見其實現)。

但在1.2.9版本並沒有看到這個feature,所以還是拭目以待吧。

writedateusedateformat

writemapnullvalue

cocoaPods的安裝和使用總結

cocoapods是ios最常用的第三方類庫管理工具,絕大部分有名的開源類庫都支援cocoapods。cocoapods是用ruby實現的,要想使用它首先需要有ruby的環境。幸運的是os x系統預設已經可以執行ruby了,因此我們只需執行以下命令 sudo gem install cocoapod...

session和cookie的使用總結

session和cookie的使用總結 session和cookie都是asp.net中的內建物件,至於他們有什麼區別,在這裡就不在多說,現在來說說一些比較實用點的東西 我們知道 都有乙個後台管理系統,其中有登入和退出兩個功能,在登入的時候我們往往會把使用者的資訊儲存到session或者cookie...

NPN和PNP的使用總結

1 區別 npn 是用 b e 的電流 ib 控制 c e 的電流 ic e極電位最低,且正常放大時通常c極電位最高,即 vc vb ve pnp 是用 e b 的電流 ib 控制 e c 的電流 ic e極電位最高,且正常放大時通常c極電位最低,即 vc vb ve 如今流行的電路圖畫法,陽上陰下...