天天看點

fastjson解析json字元串,key缺少雙引号導緻下遊服務無法解析背景說明Fastjson SerializerFeature介紹fastjson WRITE_MAP_NULL_FEATURES 案列說明結論

背景說明

在使用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也存在這樣的問題,但其可以正常解析含有"-"的特殊字元,無法解析包含":"情況。