如何使用Jackson将空字符串反序列化为属性为null的对象
问题原因
自定义反序列化器不生效的核心逻辑:Jackson在执行绑定到具体类型的反序列化器前,会先从输入流读取第一个JSON顶层token(如对象起始符{)。空字符串输入下,读取首个token时就直接碰到流末尾,提前抛出MismatchedInputException,根本不会进入你为A类定义的反序列化逻辑。
可行方案
根据场景二选一即可:
- 方案一:解析入口做空判断(最推荐,逻辑无隐式依赖,维护成本最低)
你已经在拦截器层统一把204响应的响应体替换为空字符串,直接在解析逻辑前加一层判断即可,不需要修改Jackson全局配置:
// 响应解析逻辑示例 val responseContent = ... // 拦截器处理后拿到的响应内容 val result: A = if (responseContent.isBlank()) { A(value = null) } else { objectMapper.readValue(responseContent, A::class.java) }
这个方案完全不会影响其他接口的反序列化规则,逻辑显式,不会出现全局配置带来的意外兼容问题。
- 方案二:全局配置ObjectMapper统一处理空输入
如果你有大量类都需要兼容空字符串返回默认空实例的场景,可以修改ObjectMapper配置,提前拦截空输入异常:
- 先注册Jackson的Kotlin模块,保证Jackson可以正确构造Kotlin类实例、为可空属性填充null值
- 添加空输入异常处理器,在抛出
MismatchedInputException前返回默认实例
参考配置代码:
val objectMapper = ObjectMapper().apply { // 注册Kotlin模块 registerModule(KotlinModule.Builder().build()) // 注册空输入异常处理器 addHandler(object : DeserializationProblemHandler() { override fun handleUnexpectedEOF( ctxt: DeserializationContext, p: JsonParser, targetType: JavaType ): Any { // 匹配到目标类型A时,直接返回value为null的实例 if (targetType.rawClass == A::class.java) { return A(value = null) } return super.handleUnexpectedEOF(ctxt, p, targetType) } }) }
配置完成后,直接调用objectMapper.readValue("", A::class.java)就可以得到A(value=null)的实例,正常JSON内容也会按规则反序列化,不会影响原有逻辑。
注意:不建议直接开启
DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT全局配置,该配置会把所有位置出现的空字符串都识别为null,包括正常JSON里的字段值,可能导致其他接口的反序列化结果不符合预期。
内容的提问来源于stack exchange,提问作者Ilya E
相关产品推荐
相关产品推荐

