Spring REST API如何限制HTTP请求中的未定义属性
首先确认你的假设是完全正确的:Spring默认依赖Jackson处理JSON的序列化/反序列化,而Jackson的默认行为就是忽略DTO中未定义的额外字段,不会主动抛出错误。要实现“严格校验输入JSON,禁止出现DTO外字段”的需求,我们可以通过Jackson的配置来实现,下面提供两种实用方案:
方案一:在DTO类上添加注解(局部生效)
直接在你的EmployeeDTO类上添加@JsonIgnoreProperties(ignoreUnknown = false)注解,将默认的ignoreUnknown属性从true改为false。这样当JSON输入包含未定义字段时,Jackson会抛出JsonMappingException,Spring会自动将其转换为400 Bad Request响应返回给客户端。
修改后的DTO代码示例:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = false) public class EmployeeDTO { private long id; private String name; private Boolean flag; private String dept; // 省略getXXX & setXXX方法 }
方案二:全局配置(所有DTO生效)
如果你的项目中有多个DTO类,不想逐个添加注解,可以通过Spring配置全局开启Jackson的“未知字段报错”特性。
Java配置方式
创建一个Spring配置类,注册自定义的ObjectMapper Bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration public class JacksonGlobalConfig { @Bean public ObjectMapper customObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); // 开启未知字段校验,遇到未定义字段直接报错 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); return objectMapper; } }
XML配置方式
如果你的项目使用XML配置,可以在Spring配置文件中添加如下配置:
<!-- 配置自定义ObjectMapper,开启未知字段报错 --> <bean id="customObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"> <property name="failOnUnknownProperties" value="true"/> </bean> <!-- 让Spring的JSON消息转换器使用自定义的ObjectMapper --> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper" ref="customObjectMapper"/> </bean>
验证效果
当你传入包含额外字段的JSON请求时,比如:
{ "id":100, "name":"Ram", "flag" : false, "dept" :"Software", "extra1":"unwanted", "extra2" :"This also unwanted" }
此时Spring会返回400 Bad Request响应,响应体中会包含类似如下的错误提示:
Unrecognized field "extra1" (class com.yourpackage.EmployeeDTO), not marked as ignorable (4 known properties: "id", "name", "flag", "dept"])
这样就严格限制了输入JSON的字段范围,达到了你的需求。
内容的提问来源于stack exchange,提问作者Venkata

