SpringBoot REST接口如何校验JSON请求体不含额外字段?
SpringBoot REST控制器校验JSON请求体不包含额外字段的方案
Bean Validation(如@Valid)仅校验实体类已声明字段的规则,无法检测请求体中的额外字段。针对这个问题,以下是几种实用的解决方法:
方法1:全局开启Jackson未知字段校验
通过配置Jackson的反序列化规则,让所有接口在遇到未知字段时直接抛出异常。
配置方式
在application.properties(或application.yml)中添加配置:
spring.jackson.deserialization.fail-on-unknown-properties=true
全局异常处理
为了返回友好的错误响应,添加全局异常处理器捕获Jackson的JsonMappingException:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(JsonMappingException.class) public ResponseEntity<String> handleUnknownFieldException(JsonMappingException e) { String unknownField = e.getPath().get(0).getFieldName(); return ResponseEntity.badRequest().body(String.format("请求包含不允许的字段: %s", unknownField)); } }
这种方法适合整个项目需要严格校验请求字段的场景,配置简单,全局生效。
方法2:针对单个实体类配置校验
如果只需要对特定实体类做额外字段校验,在实体类上添加@JsonIgnoreProperties注解,指定不忽略未知字段:
修改实体类
@JsonIgnoreProperties(ignoreUnknown = false) public class User { @NotBlank(message = "Name is mandatory") private String name; // getter、setter方法 }
这样只有User类在反序列化时会校验未知字段,其他实体类不受影响,灵活性更高。
方法3:自定义校验注解(进阶方案)
如果需要更灵活的校验逻辑(比如自定义错误信息、允许部分例外字段),可以实现自定义校验注解:
1. 定义自定义注解
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = NoExtraFieldsValidator.class) public @interface NoExtraFields { String message() default "请求包含不允许的额外字段"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. 实现校验器
public class NoExtraFieldsValidator implements ConstraintValidator<NoExtraFields, Object> { private ObjectMapper objectMapper = new ObjectMapper(); @Override public boolean isValid(Object value, ConstraintValidatorContext context) { try { String json = objectMapper.writeValueAsString(value); Map<String, Object> requestFields = objectMapper.readValue(json, Map.class); Field[] declaredFields = value.getClass().getDeclaredFields(); Set<String> validFields = Arrays.stream(declaredFields) .map(Field::getName) .collect(Collectors.toSet()); for (String field : requestFields.keySet()) { if (!validFields.contains(field)) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate( String.format("不允许的字段: %s", field) ).addConstraintViolation(); return false; } } return true; } catch (JsonProcessingException e) { return false; } } }
3. 在控制器中使用
@PostMapping(path = "/user") public ResponseEntity addUser(@Valid @NoExtraFields @RequestBody User user) throws Exception { userService.save(user); return new ResponseEntity<>(HttpStatus.OK); }
这种方法可以完全自定义校验逻辑,但实现相对复杂,适合特殊业务场景。
内容的提问来源于stack exchange,提问作者user1171171
相关产品推荐
相关产品推荐

