Jackson-databind反序列化缺失JSON属性时赋值为null而非默认值问题
问题根因
该现象不是Jackson 2.12.x系列小版本变更导致的行为差异,核心是两个注解使用认知误区和Lombok框架配合问题:
@JsonSetter(nulls = Nulls.AS_EMPTY)的生效范围有限:该配置仅在JSON中显式传入对应属性、且属性值为null时触发,将null转换为空字符串;如果JSON中完全缺失该属性,Jackson默认不会调用对应setter方法,该配置完全不生效。@JsonProperty(defaultValue = "")无实际运行时作用:这个参数仅用于生成JSON Schema时做文档标注,不会参与反序列化的默认值赋值逻辑,写了不会对运行结果产生任何影响。- Lombok注解配合的固有逻辑:字段上添加
@Builder.Default后,Lombok生成的无参构造函数不会自动写入你在字段上定义的初始值——也就是说直接调用new MyPojo()得到的实例中,标记了@Builder.Default的optionalProp、requiredProp初始值本来就是null。Jackson反序列化默认走无参构造实例化对象,只会给JSON中存在的字段调用setter赋值,缺失的字段会保留无参构造初始化的null值,最终就得到optionalProp=null的结果。
手动调用Builder构建实例时,Lombok生成的Builder逻辑会自动应用@Builder.Default标记的默认值,未手动set的optionalProp会被赋值为"",和反序列化走无参构造的初始化逻辑完全不同,结果自然有差异。
修复方案
任选以下一种方案即可解决问题:
- 方案一:让Jackson反序列化走Builder逻辑。在
MyPojo类上添加注解@JsonDeserialize(builder = MyPojo.MyPojoBuilder.class),反序列化时会直接复用Lombok生成的Builder逻辑,自动应用@Builder.Default配置的默认值,和手动编码构建Builder的结果完全一致,改动最小。 - 方案二:手动编写无参构造。不依赖Lombok生成的无参构造,自己实现无参构造方法,在方法内给两个字段手动赋默认值"",保证无参构造实例化的对象初始值符合预期,Jackson反序列化时缺失字段就会保留这个默认空字符串。
- 方案三:全局配置Jackson缺失字段处理逻辑。初始化
ObjectMapper时统一配置,对缺失的字符串类型字段默认赋值为空字符串,不过这种方式会全局生效,需要评估对项目中其他序列化场景的影响。
内容的提问来源于stack exchange,提问作者Biiiiiird
相关产品推荐
相关产品推荐

