fastjson 始終將 null 物件以 "null " 的形式返回到前端引發的原始碼解析
終於來到了 fastjson 內部。
FastJsonHttpMessageConverter
內部又呼叫了一系列的方法,最終定位到了 JavaBeanSerializer#write
的 216 行。
在這裡 fastjson 與 spring web 的連線主要是通過 GenericHttpMessageConverter
介面,FastJsonHttpMessageConverter
類實現了該介面,該介面繼承於 HttpMessageConverter
介面,特定只對 HTTP 請求和響應資料進行轉換處理。
再回過頭看下 RequestResponseBodyMethodProcessor#writeWithMessageConverters
FastJsonHttpMessageConverter
的:
JavaBeanSerializer
該類的 write 方法是最終輸出 json 格式資料的地方,其中對 null 型別物件判斷是否要以 "obj": null"
形式輸出的關鍵程式碼如下:
if (propertyValue == null && !writeAsArray) { if ((!fieldSerializer.writeNull) && (!out.isEnabled(SerializerFeature.WRITE_MAP_NULL_FEATURES))) { continue; } }
continue 執行時當前成員就會跳過,不進行處理,也就不會輸出。
SerializeWriter#isEnable
方法原始碼如下
public boolean isEnabled(int feature) {
return (this.features & feature) != 0;
}
該判斷置於一個迴圈中,迴圈用於遍歷目標類的成員,進行處理並輸出。propertyValue 即為當前遍歷到成員的值。fieldSerializer 則是專門序列化當前成員的處理者。
- fieldSerializer 的 writeNull 為 false:writeNull 在其建構函式中賦值,建構函式中會藉助
@JSONField
SerializerFeature.WRITE_MAP_NULL_FEATURES
特性(實體類成員上類似這樣使用@JSONField(serialzeFeatures = {SerializerFeature.WRITE_MAP_NULL_FEATURES} )
註解)啟用的話,writeNull 才為 true,否則 false - 如果
fieldSerializer.writeNull
為 false,則需要進一步判斷,out 是一個SerializeWriter
物件,繼承自java.io.Writer
,用於輸出 json 字串,out 中攜帶了我們最初的配置
out.isEnable()
會通過 FastJsonConfig 判斷是否配置了某一特性,如上所示,並沒有配置 SerializerFeature.WRITE_MAP_NULL_FEATURES
特性,那麼為什麼 “obj”: null
還是會輸出呢 ?答案在 WRITE_MAP_NULL_FEATURES 內部
撥雲見日
可見 SerializerFeature.WRITE_MAP_NULL_FEATURES
是以下幾個特性的組合:
WriteMapNullValue WriteNullBooleanAsFalse WriteNullListAsEmpty WriteNullNumberAsZero WriteNullStringAsEmpty
fastjson 特性的處理採用的是 二進位制狀態疊加 的方式,這裡的意思是 WRITE_MAP_NULL_FEATURES 特性是其它這幾個特性的集合, 舉個栗子:
如果
0001 -> WriteNullListAsEmpty
0010 -> WriteNullBooleanAsFalse
WRITE_MAP_NULL_FEATURES = WriteNullBooleanAsFalse.getMask() | WriteNullListAsEmpty.getMask()
則
0011 -> WRITE_MAP_NULL_FEATURES
假設配置了 WriteNullListAsEmpty
0001 -> features
呼叫 out.isEnabled(SerializerFeature.WRITE_MAP_NULL_FEATURES)
0001
& 0011
0001 != 0
結果為 true
即這幾個特性任意一個配置了,那麼相當於 WRITE_MAP_NULL_FEATURES 也就配置了,這種情況下 會把 null 以 "obj": null
的形式輸出。