You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中Enum的@JsonCreator在GET请求参数中不生效问题排查

问题:自定义@JsonCreator处理枚举别名未触发

我为枚举类MyEnum编写了自定义@JsonCreator方法,用于通过别名匹配枚举实例,但调用GET接口传入type参数为"12"时,该方法未触发,反而抛出枚举常量不存在的异常。

相关代码

Controller接口:

@GetMapping(value = "/path/{pathVar1}")
public Response getValue(
    @PathVariable String pathVar1,
     @RequestParam(required = false, name = "type") MyEnum type)

枚举类MyEnum:

@AllArgsConstructor
@Getter
public enum MyEnum {

  A_12(Set.of("a", "12"));

  private Set<String> aliases;

  @JsonCreator
  public static MyEnum forValues(@JsonProperty("type") String type) {
    return Arrays.stream(MyEnum.values())
        .filter(s -> s.getAliases().stream().anyMatch(a -> StringUtils.equalsIgnoreCase(a, type)))
        .findFirst()
        .orElseThrow(() -> new RuntimeException("aa"));
  }
}

报错信息

Caused by: java.lang.IllegalArgumentException: No enum constant MyEnum.12
原因分析

@JsonCreator是Jackson的注解,仅在Jackson处理JSON序列化/反序列化场景下生效。但@RequestParam的参数解析默认使用Spring自带的StringToEnumConverterFactory,它只会尝试直接匹配枚举的原始名称(比如A_12),不会触发Jackson的@JsonCreator方法,因此传入别名"12"时会抛出常量不存在的异常。

解决方案

有两种常用方式实现枚举别名的请求参数解析:

方法一:实现Spring的Converter接口(全局生效)

自定义转换器并注册到Spring容器,让框架用它来解析MyEnum类型的参数:

@Component
public class MyEnumConverter implements Converter<String, MyEnum> {
    @Override
    public MyEnum convert(String source) {
        return Arrays.stream(MyEnum.values())
                .filter(s -> s.getAliases().stream().anyMatch(a -> StringUtils.equalsIgnoreCase(a, source)))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("无效的type参数:" + source));
    }
}

Spring会自动识别并注册该转换器,之后所有@RequestParam中的MyEnum类型参数都会通过它解析别名。

方法二:使用@InitBinder注册自定义编辑器(局部/全局生效)

局部生效(当前Controller)

在目标Controller中添加@InitBinder方法,注册自定义属性编辑器:

@Controller
public class MyController {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(MyEnum.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                MyEnum myEnum = Arrays.stream(MyEnum.values())
                        .filter(s -> s.getAliases().stream().anyMatch(a -> StringUtils.equalsIgnoreCase(a, text)))
                        .findFirst()
                        .orElseThrow(() -> new IllegalArgumentException("无效的type参数:" + text));
                setValue(myEnum);
            }
        });
    }

    // 你的接口方法...
}

全局生效

定义@ControllerAdvice类,在其中添加@InitBinder方法,即可对所有Controller生效:

@ControllerAdvice
public class GlobalEnumBinder {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 同上的编辑器注册逻辑
    }
}

内容的提问来源于stack exchange,提问作者Patan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 14:16:21