如何解決Fastjson轉MAP時嵌套集合中排序非原始順序的問題

JSON轉對象在開發中是一個常規且普遍的操作,爲了增加開發效率經常會使用第三方JSON處理類庫,其中Fastjson是比較受歡迎的JSON處理類庫之一。
在最近的一次使用中,就遇到了一個問題,JSON轉Map後因順序發生了變化,造成依賴參數順序的操作不能正常執行。
解決該問題的方法如下:

String jsonStr = "{\"J2\":\"A\",\"J1\":\"B\",\"listMap\":[{\"I2\":\"C\",\"I1\":\"D\",\"I3\":\"E\"}]}";
Map<String, Object> jsonMap = JSON.parseObject(jsonStr, Map.class, Feature.OrderedField);

原因分析

在此之前的開發中,JSON轉實體對象時,不需要關心轉換後對象的順序問題,所以並未深究順序變化的原因。既然遇到了這個問題就查下原因吧。

{"J2":"A","J1":"B","listMap":[{"I2":"C","I1":"D","I3":"E"}]}

如以上JSON字符串,如果使用如下方式轉爲Map,就會出現轉後的Map會按照KEY的自然順序排序。

String jsonStr = "{\"J2\":\"A\",\"J1\":\"B\",\"listMap\":[{\"I2\":\"C\",\"I1\":\"D\",\"I3\":\"E\"}]}";
Map<String, Object> jsonMap = JSON.parseObject(jsonStr, Map.class);

轉換後Map的排列順序如下圖:
在這裏插入圖片描述出現這種問題,首先想到的是,Fastjson在轉換Map時,實例化的Map爲HashMap,HashMap本身有默認的排序算法,根據hashcode值進行排序。所以講轉換方式改爲如下代碼

String jsonStr = "{\"J2\":\"A\",\"J1\":\"B\",\"listMap\":[{\"I2\":\"C\",\"I1\":\"D\",\"I3\":\"E\"}]}";
Map<String, Object> jsonMap = JSON.parseObject(jsonStr, LinkedHasMap.class);

最終運行結果如下,只有外層Key順序一致,內層嵌套集合轉換時,順序依然有變化。
圖:
在這裏插入圖片描述
最終跟蹤代碼發現,Fastjson的DefaultJSONParser類下在轉換內層Json依然會實例化一個Map對象,如下代碼:

public JSONObject(int initialCapacity, boolean ordered) {
    if (ordered) {
        this.map = new LinkedHashMap(initialCapacity);
    } else {
        this.map = new HashMap(initialCapacity);
    }
}

ordered默認爲false,會默認實例化HashMap,所以內存嵌套依然是非固定順序的。
所以只需要改變爲ordered=true即可使用LinkedHashMap實例化Map對象。最終找到了解決了該問題的方法。

之前用Fastjson並未深入探究更多使用功能,現在發現還有Feature這個枚舉對象,用於擴展Fastjson功能。具體Feature使用細則,後續再研究吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章