fastjson 始终将 null 对象以 "null " 的
接上篇:fastjson 始终将 null 对象以 "null " 的形式返回到前端引发的源码解析 - 上:从 DispatcherServlet 出发
终于来到了 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 则是专门序列化当前成员的处理者。
- 首先值为 null 并且 SerializerFeature.BeanToArray 特性未启用
- fieldSerializer 的 writeNull 为 false:writeNull 在其构造函数中赋值,构造函数中会借助
@JSONField
注解初始化 FieldSerializer 的成员,其中如果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 内部
拨云见日
image.png可见 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
的形式输出。