SpringBoot中使用@Valid与@RequestBody时如何检测JSON请求额外字段
方案1:通过Jackson反序列化配置直接检测多余字段(推荐)
该方案无需手动提取原始JSON,Spring Boot默认使用Jackson完成JSON反序列化,自带多余字段校验能力,有两种配置方式可选:
- 仅对
InfoRequest类生效:直接在InfoRequest类上添加注解即可
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = false) public class InfoRequest { // 原有字段Name、Age等保持不变 }
- 全局所有接口生效:在
application.yml(或application.properties)中添加配置
spring: jackson: deserialization: fail-on-unknown-properties: true
配置完成后,只要请求JSON中出现InfoRequest未定义的字段,Jackson反序列化时会直接抛出UnrecognizedPropertyException,你可以通过全局异常处理器捕获该异常返回自定义错误提示,完全不需要修改现有接口代码,也符合不修改infoRequest参数类型的要求。
方案2:手动提取原始请求JSON做自定义校验
如果你有特殊的自定义校验逻辑,需要自行拿到完整JSON分析,可以通过ContentCachingRequestWrapper读取请求体,不会影响原有@RequestBody的参数解析流程:
第一步:添加请求缓存过滤器,避免请求流被读取后无法二次使用
import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.ContentCachingRequestWrapper; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class CacheRequestBodyFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request); filterChain.doFilter(wrappedRequest, response); } }
第二步:在接口中注入HttpServletRequest读取缓存的原始请求体
@PostMapping(value = "GetInfo") public ResponseEntity<Person> getOffers(@Valid @RequestBody InfoRequest infoRequest, HttpServletRequest request) throws IOException { // 从缓存包装类中读取原始JSON内容 ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request; String rawJson = new String(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding()); // 此处可添加自定义校验逻辑,比如用JSON工具解析rawJson,对比InfoRequest类的字段列表,存在多余字段直接抛出异常 Person person = PersonGenerator.getOffers(infoRequest); return new ResponseEntity<>(person, HttpStatus.OK); }
内容的提问来源于stack exchange,提问作者Anıl Kırıkkaya
相关产品推荐
相关产品推荐

