Jackson Kotlin忽略Null值失效:setSerializationInclusion不生效问题
Kotlin Jackson反序列化忽略Null值并保留默认值
问题背景
需要在JSON反序列化时,将字段的Null值忽略,直接使用字段定义的默认值填充,但不想把字段设为可空类型——程序逻辑中该值不允许为Null,仅为兼容旧版本数据才需要处理JSON中的Null值。
尝试使用setSerializationInclusion(JsonInclude.Include.NON_NULL)全局配置,以及在字段上添加@JsonInclude(JsonInclude.Include.NON_NULL)注解,均无效果。执行示例代码时抛出NullPointerException: Parameter specified as non-null is null: method icu.samnyan.aqua.spring.TestA.setS, parameter <set-?>,无法正常解析。
复现代码
import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.databind.ObjectMapper val JACKSON = ObjectMapper().apply { setSerializationInclusion(JsonInclude.Include.NON_NULL) setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL) } class TestA { @JsonInclude(JsonInclude.Include.NON_NULL) var s: String = "" } fun main() { println(JACKSON.readValue("""{"s":null}""", TestA::class.java).toString()) }
核心问题
JsonInclude.Include.NON_NULL是序列化阶段的配置,作用是将对象转为JSON时忽略值为Null的字段,完全不影响反序列化逻辑。反序列化时,Jackson会尝试把JSON中的Null值赋值给非可空字段,而Kotlin的非可空字段setter会校验参数非空,因此抛出空指针异常。
解决方案
方案1:字段级注解控制
在字段上添加@JsonSetter(nulls = Nulls.SKIP)注解,指定当字段值为Null时跳过赋值,保留字段默认值:
import com.fasterxml.jackson.annotation.JsonSetter import com.fasterxml.jackson.annotation.Nulls import com.fasterxml.jackson.databind.ObjectMapper val JACKSON = ObjectMapper() class TestA { @JsonSetter(nulls = Nulls.SKIP) var s: String = "" } fun main() { println(JACKSON.readValue("""{"s":null}""", TestA::class.java).s) // 输出:"" }
方案2:全局配置统一处理
如果需要批量处理所有非可空字段,可通过全局配置让Jackson在反序列化时跳过Null值的赋值操作:
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.registerKotlinModule import com.fasterxml.jackson.annotation.JsonSetter import com.fasterxml.jackson.annotation.Nulls val JACKSON = ObjectMapper().apply { // 注册Kotlin模块,更好支持Kotlin特性 registerKotlinModule() // 配置全局setter处理Null值的策略:跳过赋值 setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) // 可选:允许基本类型接收Null值(如果有基本类型字段需要处理) configure(DeserializationFeature.ACCEPT_NULL_FOR_PRIMITIVES, true) } class TestA { var s: String = "" } fun main() { println(JACKSON.readValue("""{"s":null}""", TestA::class.java).s) // 输出:"" }
关键说明
- 区分序列化和反序列化配置:
JsonInclude.NON_NULL只影响对象转JSON的过程,和JSON转对象的反序列化无关。 - Kotlin非可空字段的setter自带非空校验,必须显式配置Jackson跳过Null值赋值,才能保留字段默认值。
内容的提问来源于stack exchange,提问作者Hykilpikonna
相关产品推荐
相关产品推荐

