SpringBoot:如何区分默认null与显式设置的null?
如何区分请求体中默认null与显式设置的null?
场景代码
UserDto 类
@Data public class UserDto { private String name; }
Controller 接口
@PatchMapping(path="/users") public String updateUser(@RequestBody UserDto userDto){ log.info(userDto.toString()); return "hello word"; }
测试情况
尝试两种请求体:
- 空请求体
{ }
- 显式设置name为null
{ "name":null }
两种请求打印结果均为:
UserDto(name=null)
需要区分这两种场景:前者是客户端未传递name字段,后者是客户端主动设置name为null。
解决方案
方法1:用Map<String, Object>直接接收请求体
直接通过Map的containsKey()方法判断字段是否存在,简单直观:
@PatchMapping(path="/users") public String updateUser(@RequestBody Map<String, Object> requestMap){ boolean hasNameField = requestMap.containsKey("name"); if(hasNameField){ Object nameValue = requestMap.get("name"); log.info("客户端主动设置name为: {}", nameValue); }else{ log.info("客户端未传递name字段"); } return "hello word"; }
方法2:使用JsonNode接收请求体
借助Jackson的JsonNode对象,用has()方法判断字段是否存在:
@PatchMapping(path="/users") public String updateUser(@RequestBody JsonNode jsonNode){ if(jsonNode.has("name")){ JsonNode nameNode = jsonNode.get("name"); if(nameNode.isNull()){ log.info("客户端显式设置name为null"); }else{ log.info("客户端设置name为: {}", nameNode.asText()); } }else{ log.info("客户端未传递name字段"); } return "hello word"; }
方法3:自定义DTO追踪字段赋值状态
给DTO添加标记字段,通过@JsonSetter钩子记录字段是否被主动赋值,适合需要保持DTO结构的场景:
@Data public class UserDto { private String name; // 标记name字段是否被请求体赋值过 private boolean nameSet = false; @JsonSetter("name") public void setName(String name) { this.name = name; this.nameSet = true; } // 序列化时忽略标记字段 @JsonIgnore public boolean isNameSet() { return nameSet; } }
接口中判断逻辑:
@PatchMapping(path="/users") public String updateUser(@RequestBody UserDto userDto){ if(userDto.isNameSet()){ log.info("客户端传递了name字段,值为: {}", userDto.getName()); }else{ log.info("客户端未传递name字段"); } return "hello word"; }
内容的提问来源于stack exchange,提问作者Michael Xia
相关产品推荐
相关产品推荐

