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

Jackson缺失属性时设0而非抛异常的全局配置诉求

Jackson全局配置:缺失必填基本类型属性时触发反序列化失败

问题场景

请求JSON示例:

{ "name" : "test" }

对应的Kotlin数据类:

data class DTO(val name: String, val maxValue: Long)

当前问题:Jackson会自动将缺失的maxValue设为0,但实际需要全局配置让所有缺失的基本类型属性触发反序列化失败,且不接受@JsonProperty(required = true)这类局部注解方案;之前尝试的DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES仅对显式传入null的情况生效,对属性缺失场景无效。

解决方案

Jackson没有直接的全局开关实现这个需求,但可以通过自定义BeanDeserializerModifier来全局校验所有基本类型属性的存在性:

1. 实现自定义BeanDeserializerModifier

这个类会在反序列化完成后,检查所有基本类型字段是否是因属性缺失而保留默认值:

import com.fasterxml.jackson.databind.BeanDescription
import com.fasterxml.jackson.databind.DeserializationConfig
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.deser.BeanDeserializer
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier
import com.fasterxml.jackson.databind.exc.MismatchedInputException
import java.lang.reflect.Field

class RequiredPrimitiveModifier : BeanDeserializerModifier() {
    override fun modifyDeserializer(
        config: DeserializationConfig,
        beanDesc: BeanDescription,
        deserializer: JsonDeserializer<*>
    ): JsonDeserializer<*> {
        if (deserializer is BeanDeserializer) {
            return object : BeanDeserializer(deserializer) {
                override fun deserialize(p: com.fasterxml.jackson.databind.JsonParser, ctxt: com.fasterxml.jackson.databind.DeserializationContext): Any {
                    val bean = super.deserialize(p, ctxt)
                    // 遍历所有基本类型字段,校验是否因属性缺失导致使用默认值
                    bean::class.java.declaredFields.forEach { field ->
                        field.isAccessible = true
                        if (field.type.isPrimitive) {
                            val defaultValue = when (field.type) {
                                Long::class.javaPrimitiveType -> 0L
                                Int::class.javaPrimitiveType -> 0
                                Boolean::class.javaPrimitiveType -> false
                                // 可根据需求扩展其他基本类型(如Short、Byte等)
                                else -> null
                            }
                            defaultValue?.let { default ->
                                if (field.get(bean) == default) {
                                    // 检查JSON中是否存在该属性
                                    val parsedJson = p.parsedObject
                                    if (!parsedJson.has(field.name)) {
                                        throw MismatchedInputException.from(
                                            p,
                                            "Required primitive property '${field.name}' is missing from JSON",
                                            p.currentToken,
                                            beanDesc.beanClass
                                        )
                                    }
                                }
                            }
                        }
                    }
                    return bean
                }
            }
        }
        return deserializer
    }
}

2. 注册到ObjectMapper

将自定义的Modifier注册到全局的ObjectMapper实例中:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule

val globalObjectMapper = ObjectMapper().apply {
    // 注册Kotlin模块,支持Kotlin数据类序列化/反序列化
    registerKotlinModule()
    // 注册自定义的校验模块
    registerModule(object : com.fasterxml.jackson.databind.Module() {
        override fun getModuleName() = "RequiredPrimitiveValidationModule"
        override fun setupModule(context: com.fasterxml.jackson.databind.Module.SetupContext) {
            context.addBeanDeserializerModifier(RequiredPrimitiveModifier())
        }
    })
}

3. 验证效果

  • 当反序列化缺失maxValue的JSON时,会抛出MismatchedInputException,提示属性缺失
  • 若JSON中显式传入maxValue: 0,则可以正常完成反序列化,不会触发异常

补充说明

  • 该方案会全局作用于所有基本类型字段,无需逐个添加注解
  • 如果需要排除特定字段,可以自定义一个注解(如@OptionalPrimitive),然后在Modifier中判断字段是否带有该注解,跳过校验
  • 针对Kotlin数据类,Jackson通过构造器注入属性值,反射检查字段默认值的方式可以准确区分“显式传入默认值”和“属性缺失”两种情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:06:05