如何在Swagger场景下让Jackson拒绝布尔字段的整型输入并抛出异常
解决方案
问题根因排查
单元测试与实际运行行为不一致的核心原因,大概率是实际运行环境的ObjectMapper配置被覆盖,没有加载到你设置的Jackson反序列化规则,排查方向如下:
- 检查项目中是否存在手动实例化
ObjectMapper或自定义MappingJackson2HttpMessageConverter的代码,若未通过Jackson2ObjectMapperBuilder构建对象,application.properties/yml中的spring.jackson系列配置会完全失效 - 检查是否引入了第三方Starter(如监控、通用工具包等)修改了Jackson默认反序列化配置,强制开启了标量类型的宽松转换
你可以在实际运行的Controller中注入ObjectMapper,断点查看以下配置项的开关值,与单元测试环境的配置做对比,即可确认差异:
objectMapper.getDeserializationConfig().isEnabled(DeserializationFeature.ALLOW_COERCION_OF_SCALARS); objectMapper.getDeserializationConfig().isEnabled(DeserializationFeature.ACCEPT_BOOLEAN_AS_NUMBER);
修复方案
方案1:配置文件全局生效(推荐)
如果是Spring Boot 2.2+ + Jackson 2.10+版本,直接在配置文件中添加以下规则即可关闭数字转布尔的宽松转换:
spring: jackson: deserialization: # 关闭所有标量类型的强制转换(数字转布尔、字符串转数字等都会被禁用) allow-coercion-of-scalars: false # 单独禁用布尔类型接受数字入参 accept-boolean-as-number: false
方案2:自定义严格布尔反序列化器(无依赖兼容)
如果配置项不生效或者需要更严格的控制,直接自定义反序列化器覆盖默认的Boolean解析逻辑:
- 编写反序列化实现类
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; public class StrictBooleanDeserializer extends JsonDeserializer<Boolean> { @Override public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonToken currentToken = parser.currentToken(); if (JsonToken.VALUE_TRUE.equals(currentToken)) { return Boolean.TRUE; } else if (JsonToken.VALUE_FALSE.equals(currentToken)) { return Boolean.FALSE; } context.reportWrongTokenException(parser, JsonToken.VALUE_TRUE, "Only standard JSON boolean values (true/false) are allowed"); return null; } }
- 全局注册反序列化器
import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public Module strictBooleanModule() { SimpleModule module = new SimpleModule(); module.addDeserializer(Boolean.class, new StrictBooleanDeserializer()); module.addDeserializer(boolean.class, new StrictBooleanDeserializer()); return module; } }
如果你的资源类是通过OpenAPI生成的,也可以在yaml对应字段上指定反序列化器,无需全局生效:
myFlag: type: boolean example: false x-jackson-deserializer: com.yourpackage.StrictBooleanDeserializer
内容的提问来源于stack exchange,提问作者Tim Hanson
相关产品推荐
相关产品推荐

