Enum转换报错:No enum constant问题排查与修复求助
问题排查与修复方案
错误根源
报错「No enum constant com.edd.bookrental.models.user.Role."ADMIN"」的核心原因是请求体解析后传入Role.valueOf()的字符串带双引号:
- 当直接传
"ADMIN"时,@RequestBody String role接收的实际内容是带双引号的字符串(如"\"ADMIN\""),调用trim()后仍为"ADMIN"(含引号),而枚举常量是ADMIN(无引号),匹配失败。 - 当传
{"role": "ADMIN"}时,接收的是整个JSON字符串(如"{\"role\": \"ADMIN\"}"),解析后完全不符合枚举常量格式,直接触发错误。
修复方案
方案1:改用DTO类接收JSON请求(推荐)
这是REST接口的标准做法,能正确解析JSON格式的请求体:
- 创建请求DTO类:
public class RoleAssignRequest { private String role; // Getter & Setter public String getRole() { return role; } public void setRole(String role) { this.role = role; } }
- 修改Controller层代码:
/** Admin can assign roles to other users **/ @PostMapping(path = "/user/{id}/role") public ResponseEntity<?> updateUserRole(@PathVariable Long id, @RequestBody RoleAssignRequest request) { try { // 清理角色字符串:转大写+去空格 String roleStr = request.getRole().toUpperCase().trim(); Role parsedRole = Role.valueOf(roleStr); userService.assignRole(id, parsedRole); return new ResponseEntity<>(parsedRole, HttpStatus.ACCEPTED); } catch (IllegalArgumentException e) { return new ResponseEntity<>("无效角色类型:" + request.getRole(), HttpStatus.BAD_REQUEST); } catch (Exception e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } }
此时前端传{"role": "ADMIN"}就能被正确解析,Spring会自动将JSON中的role字段映射到DTO的role属性。
方案2:兼容纯文本请求(带/不带引号)
如果需要支持直接传纯文本(如ADMIN或"ADMIN"),可以在Controller中先清理字符串的引号:
@PostMapping(path = "/user/{id}/role") public ResponseEntity<?> updateUserRole(@PathVariable Long id, @RequestBody String role) { try { // 去除前后双引号,转大写+去空格 String cleanRole = role.replaceAll("^\"|\"$", "").toUpperCase().trim(); Role parsedRole = Role.valueOf(cleanRole); userService.assignRole(id, parsedRole); return new ResponseEntity<>(parsedRole, HttpStatus.ACCEPTED); } catch (IllegalArgumentException e) { return new ResponseEntity<>("无效角色类型:" + role, HttpStatus.BAD_REQUEST); } catch (Exception e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } }
方案3:增强枚举的解析灵活性(可选)
在枚举类中添加自定义解析方法,同时支持匹配枚举名(ADMIN)和roleText(admin),并自动处理引号:
@Getter public enum Role { USER("user"), ADMIN("admin"); String roleText; Role(String roleText) { this.roleText = roleText; } public static Role fromString(String input) { if (input == null) { throw new IllegalArgumentException("角色不能为空"); } // 清理输入:去引号、转小写、去空格 String cleaned = input.replaceAll("^\"|\"$", "").trim().toLowerCase(); for (Role role : Role.values()) { // 匹配枚举名(忽略大小写)或roleText if (role.name().toLowerCase().equals(cleaned) || role.roleText.equals(cleaned)) { return role; } } throw new IllegalArgumentException("No enum constant for role: " + input); } }
然后在Controller中替换Role.valueOf()为Role.fromString()即可。
验证注意事项
- 发送JSON请求时,确保Postman的
Content-Type设置为application/json。 - 若使用纯文本请求,设置
Content-Type为text/plain。
内容的提问来源于stack exchange,提问作者merxi beaucoup
相关产品推荐
相关产品推荐

