如何在Spring Boot请求对象中传递Enum数据,解决POST请求Bad Request错误
问题根因
你在Days枚举上添加了@JsonFormat(shape = JsonFormat.Shape.OBJECT)注解,仅配置了枚举序列化时输出为JSON对象,但Jackson默认没有提供对应结构的反序列化逻辑,所以收到前端传入的day对象时无法转换为Days枚举实例,触发400 Bad Request错误。
解决方案
方案1:在枚举内添加@JsonCreator注解(最简便)
直接在Days枚举类中添加静态构造方法,标记为Jackson的反序列化入口,根据传入的key匹配对应枚举即可,代码示例:
@JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum Days { // 原有枚举值、属性、getter保持不变 MONDAY(1,"Monday"), TUESDAY(2,"Tuesday"),THURSDAY(4,"Thursday"), FRIDAY(5,"Friday"), SATURDAY(6,"Saturday"), SUNDAY(7,"Sunday"); private final Integer key; private final String value; Days(Integer key, String value) { this.key = key; this.value = value; } public Integer getKey() { return key; } public String getValue() { return value; } // 新增反序列化入口 @JsonCreator public static Days getItemByKey(Map<String, Object> params) { Integer key = (Integer) params.get("key"); for (Days day : Days.values()) { if (day.getKey().equals(key)) { return day; } } throw new IllegalArgumentException("非法的day参数:" + params); } }
Jackson会自动识别@JsonCreator标记的方法作为反序列化入口,接收传入的JSON对象转换为Map后匹配枚举,不需要额外新增其他类。
方案2:自定义全局反序列化器
如果多个枚举都有类似需求,可以统一实现反序列化逻辑,步骤如下:
- 自定义反序列化器
public class DaysDeserializer extends StdDeserializer<Days> { public DaysDeserializer() { super(Days.class); } @Override public Days deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { JsonNode node = p.getCodec().readTree(p); int key = node.get("key").asInt(); for (Days day : Days.values()) { if (day.getKey() == key) { return day; } } throw new IllegalArgumentException("非法的day值:" + key); } }
- 在Days枚举上绑定反序列化器
@JsonFormat(shape = JsonFormat.Shape.OBJECT) @JsonDeserialize(using = DaysDeserializer.class) public enum Days { // 原有代码保持不变 }
补充可选方案
如果愿意调整前端传参逻辑,也可以将请求体中的day字段改为枚举名"MONDAY"或者key值1,同时调整枚举的反序列化配置即可,不过这种方式需要修改前端调用逻辑,适配成本高于上述两种后端适配方案。
内容的提问来源于stack exchange,提问作者Pradeep Virtuele
相关产品推荐
相关产品推荐

