You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson反序列化失败时为可空字段默认赋值null的通用实现方案

通用Jackson反序列化容错方案

以下提供两种适配不同场景的实现方案:


方案1:注解粒度控制(灵活推荐)

适合仅需要给指定字段开启容错的场景,不会影响全局反序列化逻辑,可适配任意类型的可空子对象。

1. 实现通用容错反序列化器

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.databind.deser.std.StdDeserializer

class NullOnErrorDeserializer<T>(private val targetType: JavaType) : StdDeserializer<T>(targetType) {
    override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): T? {
        return runCatching {
            ctxt.readValue<T>(jp, targetType)
        }.getOrNull().also {
            // 跳过错误节点剩余内容,避免影响后续字段解析
            jp.skipChildren()
        }
    }
}

2. 定义启用容错的标记注解

import com.fasterxml.jackson.annotation.JacksonAnnotation
import kotlin.annotation.AnnotationTarget.*

@Target(FIELD, VALUE_PARAMETER, PROPERTY_GETTER)
@Retention(AnnotationRetention.RUNTIME)
@JacksonAnnotation
annotation class DeserializeNullOnError

3. 注册到Jackson全局配置

import com.fasterxml.jackson.databind.Module
import com.fasterxml.jackson.databind.deser.Deserializers
import com.fasterxml.jackson.databind.module.SimpleModule
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class JacksonCustomConfig {
    @Bean
    fun nullOnErrorDeserializationModule(): Module {
        return SimpleModule().apply {
            addDeserializers(object : Deserializers.Base() {
                override fun findBeanDeserializer(
                    type: JavaType,
                    config: com.fasterxml.jackson.databind.DeserializationConfig,
                    beanDesc: com.fasterxml.jackson.databind.BeanDescription
                ) = if (beanDesc.annotated.hasAnnotation(DeserializeNullOnError::class.java)) {
                    NullOnErrorDeserializer(type)
                } else null
            })
        }
    }
}

4. 使用示例

在需要开启容错的可空字段上添加注解即可,所有子对象类型可通用:

data class FooDTO(
  @DeserializeNullOnError
  val bar: BarDTO?,
  @DeserializeNullOnError
  val other: OtherDTO?, // 其他子对象直接加注解即可复用逻辑
  val name: String
)

方案2:全局自动容错(省事)

适合所有可空子对象都需要容错的场景,无需修改现有DTO代码,全局生效。
直接注册自定义异常处理器到Jackson配置即可:

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler
import com.fasterxml.jackson.databind.module.SimpleModule
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class JacksonLenientConfig {
    @Bean
    fun globalLenientModule(): SimpleModule {
        return SimpleModule().apply {
            addHandler(object : DeserializationProblemHandler() {
                // 处理类型不匹配的异常
                override fun handleUnexpectedToken(
                    ctxt: DeserializationContext, targetType: Class<*>, 
                    token: com.fasterxml.jackson.core.JsonToken, p: JsonParser, failureMsg: String?
                ): Any? {
                    return if (!targetType.isPrimitive) {
                        p.skipChildren()
                        null
                    } else super.handleUnexpectedToken(ctxt, targetType, token, p, failureMsg)
                }

                // 处理字符串转对象的异常
                override fun handleWeirdStringValue(
                    ctxt: DeserializationContext, targetType: Class<*>, 
                    value: String, failureMsg: String?
                ): Any? {
                    return if (!targetType.isPrimitive && targetType != String::class.java) {
                        null
                    } else super.handleWeirdStringValue(ctxt, targetType, value, failureMsg)
                }
            })
        }
    }
}

内容的提问来源于stack exchange,提问作者TovrikTheThird

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:24:03