fastjson 始终将 null 对象以 "null " 的

2018-11-07  本文已影响0人  DJN_

接上篇:fastjson 始终将 null 对象以 "null " 的形式返回到前端引发的源码解析 - 上:从 DispatcherServlet 出发

终于来到了 fastjson 内部。

FastJsonHttpMessageConverter

内部又调用了一系列的方法,最终定位到了 JavaBeanSerializer#write 的 216 行。

image.png

在这里 fastjson 与 spring web 的连接主要是通过 GenericHttpMessageConverter 接口,FastJsonHttpMessageConverter 类实现了该接口,该接口继承于 HttpMessageConverter 接口,特定只对 HTTP 请求和响应数据进行转换处理。
再回过头看下 RequestResponseBodyMethodProcessor#writeWithMessageConverters 方法是怎么关联上 FastJsonHttpMessageConverter的:

image.png

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 则是专门序列化当前成员的处理者。

  1. 首先值为 null 并且 SerializerFeature.BeanToArray 特性未启用
  2. fieldSerializer 的 writeNull 为 false:writeNull 在其构造函数中赋值,构造函数中会借助 @JSONField注解初始化 FieldSerializer 的成员,其中如果 SerializerFeature.WRITE_MAP_NULL_FEATURES 特性(实体类成员上类似这样使用 @JSONField(serialzeFeatures = {SerializerFeature.WRITE_MAP_NULL_FEATURES} ) 注解)启用的话,writeNull 才为 true,否则 false
  3. 如果 fieldSerializer.writeNull 为 false,则需要进一步判断,out 是一个 SerializeWriter 对象,继承自 java.io.Writer,用于输出 json 字符串,out 中携带了我们最初的配置
image.png

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 的形式输出。

上一篇下一篇

猜你喜欢

热点阅读