fastjson解析json字符串,key缺少雙引號導致下游服務無法解析

背景說明

在使用fastjson 1.2.60版本將對象轉化爲json字符串時,爲處理Map值爲null的情況,採用了WRITE_MAP_NULL_FEATURES屬性,但該屬性解析出來的key中缺少雙引號,在key包含特殊字符時,如“-”和“:",下游服務在進行反序列化時出現無法解析的錯誤,從而出現問題。

Fastjson SerializerFeature介紹

使用fastjson解析爲字符串時,需要處理一些特殊情況,比如想要在解析後的字符串中顯示對象中爲null的字段。這個時候就需要用到fastjson的SerializerFeature序列化屬性,有以下幾個常用屬性:

屬性 含義
QuoteFieldNames 輸出key時是否使用雙引號,默認爲true
UseSingleQuotes 使用單引號而不是雙引號,默認爲false
WriteMapNullValue 是否輸出值爲null的字段,默認爲false
WriteEnumUsingToString Enum輸出name()或者original,默認爲false
UseISO8601DateFormat Date使用ISO8601格式輸出,默認爲false
WriteNullListAsEmpty List字段如果爲null,輸出爲[],而非null
WriteNullStringAsEmpty 字符類型字段如果爲null,輸出爲”“,而非null
WriteNullNumberAsZero 數值字段如果爲null,輸出爲0,而非null
WriteNullBooleanAsFalse Boolean字段如果爲null,輸出爲false,而非null
SkipTransientField 如果是true,類中的Get方法對應的Field是transient,序列化時將會被忽略。默認爲true
SortField 按字段名稱排序後輸出。默認爲false
PrettyFormat 結果是否格式化,默認爲false
WriteClassName 序列化時寫入類型信息,默認爲false。反序列化是需用到
DisableCircularReferenceDetect 消除對同一對象循環引用的問題,默認爲false
WriteSlashAsSpecial 對斜槓'/'進行轉義
BrowserCompatible 將中文都會序列化爲uXXXX格式,字節數會多一些,但是能兼容IE 6,默認爲false
WriteDateUseDateFormat 全局修改日期格式,默認爲false。JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
DisableCheckSpecialChar 一個對象的字符串屬性中如果有特殊字符如雙引號,將會在轉成json時帶有反斜槓轉移符。如果不需要轉義,可以使用這個屬性。默認爲false

除了上述的屬性之外,還有WRITE_MAP_NULL_FEATURES,是以下幾個屬性的組合:

public static final int WRITE_MAP_NULL_FEATURES
    = WriteMapNullValue.getMask()
    | WriteNullBooleanAsFalse.getMask()
    | WriteNullListAsEmpty.getMask()
    | WriteNullNumberAsZero.getMask()
    | WriteNullStringAsEmpty.getMask()
    ;

fastjson WRITE_MAP_NULL_FEATURES 案列說明

map key不包含特殊字符

public static void main(String[] args) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "小明");
        map.put("age", 12);
        map.put("sex", null);
        System.out.println(JSON.toJSONString(map)); // {"name":"小明","age":12}
        System.out.println(JSON.toJSONString(map, SerializerFeature.WriteMapNullValue)); // {"sex":null,"name":"小明","age":12}
        System.out.println(JSON.toJSONString(map, SerializerFeature.WRITE_MAP_NULL_FEATURES)); // {sex:null,name:"小明",age:12}
    }

從上面測試可以看出,使用WRITE_MAP_NULL_FEATURES,輸出的json字符串key中並不包含雙引號,再進行反序列化測試結果:

public static void main(String[] args) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "小明");
        map.put("age", 12);
        map.put("sex", null);
        String test = JSON.toJSONString(map, SerializerFeature.WRITE_MAP_NULL_FEATURES); // {sex:null,name:"小明",age:12}
        JSONObject jsonObject = JSON.parseObject(test);
        System.out.println(JSON.toJSONString(jsonObject)); // {"name":"小明","age":12}
    }

key包含特殊字符(“-” “:”)的反序列化

public static void main(String[] args) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "小明");
        map.put("age", 12);
        map.put("sex", null);
        // 包含特殊字符時 "-" 或者 ":"時
        map.put("test:test", "test");
        String test = JSON.toJSONString(map, SerializerFeature.WRITE_MAP_NULL_FEATURES);
        System.out.println(test); // {test-test:"test",sex:null,name:"小明",age:12}
        JSONObject jsonObject = JSON.parseObject(test);
        System.out.println(JSON.toJSONString(jsonObject)); // 拋出異常 com.alibaba.fastjson.JSONException
    }

結論

  • 從上面的測試可以看出WRITE_MAP_NULL_FEATURES轉化爲json字符串時key是不包含雙引號的,當key中不存在特殊字符("-"或“:")時,可以進行正常的反序列化操作,包含了上面的特殊字符時會出現無法解析的異常。
  • 另外,對於不帶雙引號的key,Gson也存在這樣的問題,但其可以正常解析含有"-"的特殊字符,無法解析包含":"情況。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章