如何在REST API的RequestBody中排除null字段值?
解决Spring Boot PATCH接口请求体null字段不被忽略的问题
问题原因
你添加的@JsonInclude(JsonInclude.Include.NON_NULL)注解仅在**序列化(将POJO转为JSON响应)时生效,控制返回结果不包含null字段;但在反序列化(将请求JSON转为POJO)**过程中,这个注解不会起作用,所以请求里的productNo: null依然会被赋值到POJO的对应字段中。
解决方案
方案1:字段级配置忽略反序列化null值
给需要忽略null的字段添加@JsonSetter(nulls = Nulls.SKIP)注解,Jackson在反序列化时遇到null值就不会设置该字段,保持字段原有默认值:
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.Nulls; import lombok.Data; @Data @JsonInclude(JsonInclude.Include.NON_NULL) public class Product { private String name; private String productId; @JsonSetter(nulls = Nulls.SKIP) private String productNo; private String targetArea; private int minimumQuantity; private double buyingPrice; private int quantity; private String selfStatus; private double sellingPrice; }
方案2:全局配置反序列化忽略null值
如果希望所有POJO在反序列化时都忽略null字段,可以添加全局Jackson配置:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.deser.std.Nulls; @Configuration public class JacksonConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { return builder -> builder.postConfigurer(mapper -> { // 设置全局反序列化时跳过null值的赋值 mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)); }); } }
方案3:针对PATCH请求的优化方案(推荐)
PATCH接口是部分更新,更适合用Map<String, Object>接收请求体,或者创建专用的更新DTO,手动处理非null字段,避免基本类型默认值的干扰(比如int类型的minimumQuantity默认是0,可能会被误更新):
@RequestMapping(value = "/update-product/{product-id}", method = RequestMethod.PATCH) public ResponseEntity<Product> updateProduct(@RequestBody Map<String, Object> updateParams, @PathVariable("product-id") String productId) { // 1. 从数据库查询原产品信息 Product originalProduct = productService.getById(productId); // 2. 遍历更新参数,只处理非null的字段 updateParams.forEach((key, value) -> { if (value == null) return; switch (key) { case "name": originalProduct.setName((String) value); break; case "targetArea": originalProduct.setTargetArea((String) value); break; case "productNo": originalProduct.setProductNo((String) value); break; // 其他字段按需处理 } }); // 3. 保存并返回更新后的产品 Product updatedProduct = productService.save(originalProduct); return new ResponseEntity<>(updatedProduct, HttpStatus.OK); }
额外注意事项
- 控制器代码中
@PathVariable (“product-id”)使用了中文引号,会导致编译错误,需改为英文引号:@PathVariable("product-id") - 测试用的JSON请求中
“targetArea: “12345”的引号是中文的,修正为:
{ "targetArea": "12345", "name": "Bucket", "productNo": null }
内容的提问来源于stack exchange,提问作者psprogrammer
相关产品推荐
相关产品推荐

