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