alibaba fastjson的JsonObject有序的實現和原始碼分析

Scotyzh發表於2023-11-02

介紹

FastJson是阿里巴巴的開源JSON解析庫,它可以解析JSON格式的字串,支援將Java Bean序列化為JSON字串,也可以從JSON字串反序列化到JavaBean。在使用的過程中,因為有序性問題導致踩了坑,看一下其底層原始碼,瞭解其有序性上的實現。

分析1:

JSONObject inputInfo = manifestDraftObj.getJSONObject("inputInfo");

這裡在使用的時候,以為get出來的資料是引用關係的,修改會影響到原先Object裡面的資料,但實際情況並不是這樣子透過get拿到的object,對這個object的修改不會影響到原先那個object,get到的object是複製出來的,可以在JSON類裡面的toJSON(Object javaObject, SerializeConfig config)方法看到,新new了個JSONObject,且內部是linkedHasMap,最終返回的是這個複製出來的Map。

image-20231102101426157

透過上述程式碼拿到的object,其實其內部已經linkedHashMap的有序Map了

至於為什麼預設是有序的LinkedHashMap,追原始碼看一看

image-20231102105225169

當一個請求進來,我們的系統會使用反射去呼叫url下指定的controller的method,同時會對引數進行初始化,會根據引數指定的型別進行初始化,這裡會進入MapDeserializer類,並且在這裡面執行deserialize()方法,生成我們當前需要的JSONObject,且是LinkedHashMap的,如下圖:

image-20231102105621588

在這裡,呼叫了_readAndBindStringKeyMap後,會將我們需要的JSONObject存到result裡面,並返回,進入這個方法看一看,這個方法會在valueDes.deserialize(p,ctxt)進行map的生成和組裝。

image-20231102105710760

進入valueDes.deserialize(p,ctxt)方法,可以看到LinkedHashMap的建立和賦值

image-20231102105842205

自此引數生成完畢,回到我們最開始的jsonobject的getObject方法,現在我們明白為什麼會是LinkdedHashMap了,在這裡(map instanceof LinkedHashMap)條件會成立,進入賦值和建立。

image-20231102101426157

分析2:

JSON.parseObject(manifestDraft.getInputDraft() , Feature.OrderedField)

parseObject預設返回的是無序的map,要得到有序需要加Feature.OrderedField

部分原始碼上的分析:

使用上述程式碼,會進入到DefaultJSONParser,在這裡建立有序的JSONObject

image-20231102110843244

在new JSONObject的時候,會進入JSONObject的構造方法,最後建立出個LinkedHashMap

image-20231102110915994

最後來到parseObject方法,完成填值

image-20231102111157557

相關文章