fastjson用自定义实现集合嵌套的空值保留

起因

今天项目中需要实现这么一个需求:要返回一个List<Map<>>,其中可能存在value为null的情况,这种情况需要保留null,返回结果为下面这种

[
	 {
		"aaa": null,
		"ccc": 2.0,
		"ddd": "3"
	},
	 {
		 "aaa": null,
		 "ccc": 2.0,
		 "ddd": "3"
	 },
	 {
		"aaa": null,
		"ccc": null,
		"ddd": "4"
	 }
]

但是我们之前的其他接口的需求是如果为null就不返回,所以为了不影响其他接口,就需要单独来定义一个序列化实现。

探索

首先我就想到了用JSONField来指定序列化

  @JSONField(serialzeFeatures = SerializerFeature.WriteMapNullValue)
  private List<Map<String, Object>> list;

结果试了一下不行,推测是由于@JSONField并不是加在Map上的,导致不能生效,跟踪代码后发现,执行了这么一句

 public final void writeWithFieldName(Object object, Object fieldName) {
        writeWithFieldName(object, fieldName, null, 0);
 }

 public final void writeWithFieldName(Object object, Object fieldName, Type fieldType, int fieldFeatures) {
        try {
            if (object == null) {
                out.writeNull();
                return;
            }

            Class<?> clazz = object.getClass();

            ObjectSerializer writer = getObjectWriter(clazz);

            writer.write(this, object, fieldName, fieldType, fieldFeatures);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

这个fieldFeatures就是我们设置的序列化的参数,可以看到我们指定的参数在这里无论是什么都会被覆盖为0,所以我们在外面指定的格式就失效了

解决

既然用默认的序列化会失效,不如我们自己实现一个不会失效的序列化,我们可以将上面的代码复制过来,然后加以改动,最终代码就成了下面这样

  @JSONField(serializeUsing = ListMapSerializer.class, serialzeFeatures = SerializerFeature.WriteMapNullValue)
  private List<Map<String, Object>> list;

  // 自定义序列化
  public static class ListMapSerializer implements ObjectSerializer {
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) {
      // 如果为空,调用默认
      if(object == null) {
        serializer.write(object);
        return;
      }
      // 不为空,调用features的序列化
      Class<?> clazz = object.getClass();
      ObjectSerializer writer = serializer.getObjectWriter(clazz);
      try {
        writer.write(serializer, object, null, null, features);
      } catch (IOException e) {
        throw new JSONException(e.getMessage(), e);
      }
    }
  }

这里在write的时候将传过来的features传进去,这样一来我们在上面指定的参数就能够正常使用了。

后记

对于fastjson的序列化,博主还不是很了解,所以对于内部代码的实现讲解的不是很详细,解决的方法可能也不是很优雅,欢迎大家指出问题,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值