
spring boot 默认不会因 json 字段类型不匹配(如数字赋值给 string 字段)而自动拒绝请求,需结合 @valid 与 bindingresult 手动捕获类型转换错误,才能实现强类型校验和 400 bad request 响应。
在 Spring MVC 中,JSON 反序列化由 Jackson 负责,而 Bean 校验(如 @NotBlank、@NotNull)仅作用于反序列化成功后的对象字段值。当客户端发送 "name": 5 时,Jackson 默认会尝试将数字 5 强转为字符串 "5"(启用 DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY 或默认字符串强制转换策略),导致校验注解根本未触发——因为字段已“合法”地被设为字符串,而非校验失败。
要真正拦截类型不匹配(如非字符串值赋给 String 字段),必须启用并检查数据绑定错误(如类型转换失败),而非仅依赖字段级约束。正确做法是在 Controller 方法中显式添加 BindingResult 参数:
@PostMapping("/register")
public ResponseEntity> register(@Valid @RequestBody Person person, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// 收集所有错误(含类型转换异常,如 "Failed to convert property 'name' of type java.lang.Integer to java.lang.String")
List errors = bindingResult.getAllErrors().stream()
.map(error -> error.getDefaultMessage())
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(Map.of("errors", errors));
}
// 处理有效请求
return ResponseEntity.ok().build();
} ⚠️ 注意事项:
- BindingResult 必须紧跟在被 @Valid 标注的参数之后,否则 Spring 无法关联校验结果;
- 若使用 Lombok,确保 @Data 或 @Setter 不干扰 Jackson 反序列化逻辑(推荐显式定义无参构造器和 setter);
- 为提升健壮性,建议全局配置 Jackson 禁用宽松类型转换:
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 禁止将数字/布尔等类型自动转为字符串
mapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
mapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
// ⚠️ 关键:禁止将非字符串值强制转为 String(需配合自定义反序列izer 或使用严格模式)
// 实际中更推荐:在 DTO 中使用 @JsonCreator + @JsonProperty 配合自定义验证逻辑
return mapper;
}
}✅ 最佳实践补充:若需彻底杜绝类型混淆,可弃用默认字符串转换,改用自定义反序列化器或采用更严格的 DTO 设计(例如用 @JsonCreator 构造函数强制校验输入类型),再辅以 @Valid + BindingResult 统一处理错误响应。这样既保证接口契约清晰,又符合 RESTful API 对 400 Bad Request 的语义要求。










