使用Postman向Spring Boot发送包含枚举数组的请求时收到Null值问题(附Postman请求、RequestDTO及返回eSexes空值的ENUM类ESex)
嘿,我之前也踩过Spring Boot接收枚举数组为null的坑,咱们一步步来排查和解决它!
假设你的代码和请求大概是这样的(如果和你的实际情况有出入,你可以调整):
1. 枚举类 ESex
public enum ESex { MALE, FEMALE, OTHER; }
2. 请求DTO类
public class UserRequestDTO { private List<ESex> eSexes; // Getter & Setter public List<ESex> getESexes() { return eSexes; } public void setESexes(List<ESex> eSexes) { this.eSexes = eSexes; } }
3. Postman请求示例
你发送的是JSON格式的POST请求,但后端接收后eSexes始终是null:
{ "eSexes": ["MALE", "FEMALE"] }
我总结了几个最容易踩的坑,你可以挨个核对:
1. 枚举反序列化规则没配置到位
Spring Boot默认用Jackson处理JSON,它对枚举的反序列化默认是匹配枚举的name()值,但如果你的枚举有自定义value,或者全局配置了特殊的序列化规则,就可能导致解析失败,直接返回null。2. 请求参数和DTO字段名不匹配
JSON是大小写敏感的!比如你DTO里是eSexes,但Postman里写成了esexes或者sexes,肯定绑定不上。3. Postman的请求头没设置对
如果没把Content-Type设为application/json,Spring Boot根本不会把请求体当成JSON解析,字段自然就是null。4. DTO缺少无参构造函数
Jackson实例化DTO时默认需要无参构造函数,如果你的DTO只有带参构造,可能会导致实例化失败,字段无法赋值。5. 枚举值大小写不匹配
比如Postman里写的是male,但枚举类里是MALE,Jackson默认严格匹配,解析失败后可能直接让整个列表变成null(如果全局配置了忽略未知值的话)。
根据上面的原因,对应解决:
方案1:给枚举配置明确的反序列化规则
这是最常用的解决办法,分两种情况:
情况A:枚举用名称(name)匹配
在枚举类上加@JsonValue注解,明确告诉Jackson用枚举的name来序列化/反序列化:
import com.fasterxml.jackson.annotation.JsonValue; public enum ESex { MALE, FEMALE, OTHER; @JsonValue public String getName() { return this.name(); } }
情况B:枚举有自定义value字段
如果你的枚举是带代码值的(比如MALE("M")),就需要同时配置@JsonValue和@JsonCreator:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; public enum ESex { MALE("M"), FEMALE("F"), OTHER("O"); private final String code; ESex(String code) { this.code = code; } @JsonValue public String getCode() { return code; } // 反序列化时根据传入的字符串匹配枚举 @JsonCreator public static ESex fromCode(String code) { for (ESex sex : ESex.values()) { // 可以加equalsIgnoreCase支持大小写不敏感 if (sex.code.equals(code)) { return sex; } } throw new IllegalArgumentException("无效的性别值: " + code); } }
方案2:确保请求参数和DTO字段完全匹配
如果不想严格区分大小写,或者JSON键名和DTO字段名不一样,可以用@JsonProperty注解明确绑定:
import com.fasterxml.jackson.annotation.JsonProperty; public class UserRequestDTO { @JsonProperty("eSexes") // 强制绑定JSON里的"eSexes"键 private List<ESex> eSexes; // Getter & Setter }
方案3:修正Postman的请求配置
在Postman的Headers里添加:
- Key:
Content-Type - Value:
application/json
同时确保请求体选择raw -> JSON格式,不要用form-data或x-www-form-urlencoded(如果用表单的话,枚举数组的格式是eSexes=MALE&eSexes=FEMALE,需要后端用@RequestParam接收)。
方案4:给DTO添加无参构造函数
如果你的DTO没有无参构造,一定要加上:
public class UserRequestDTO { private List<ESex> eSexes; // 无参构造函数 public UserRequestDTO() {} // Getter & Setter }
方案5:统一枚举值的大小写
要么把Postman里的枚举值改成和枚举类一致的大小写,要么在@JsonCreator方法里做忽略大小写的判断(比如方案1的情况B里把equals改成equalsIgnoreCase)。
修改后,在后端接口里加个日志打印,看看接收情况:
@RestController @RequestMapping("/users") public class UserController { @PostMapping public ResponseEntity<String> createUser(@RequestBody UserRequestDTO requestDTO) { System.out.println("接收的性别列表: " + requestDTO.getESexes()); return ResponseEntity.ok("请求成功"); } }
如果日志里能输出[MALE, FEMALE],说明问题搞定啦!
内容的提问来源于stack exchange,提问作者Giovanni Caggianella

