在 Spring 框架中对枚举类型的序列化/反序列化是有限制的。
假设如下面这样在某些情况下就不能正常工作:
1 2 3 4 5 6 7 8 9 public enum PayChannelEnum implements BaseEnum<Integer> { ALIPAY(20), WECHARPAY(21); private Integer code; }
比如对于具有 PayChannelEnum
类型的参数的 HTTP 接口来说:
如果请求 /get?payChannel=ALIPAY
,运行OK。但如果请求 /get?payChannel=20
, 就会抛出 MethodArgumentTypeMismatchException
异常。
–
日常开发中主要有如下几种场景使用枚举:
GET
方法, 参数列表中有枚举类型/自定义参数包含枚举;
POST
方法 Form
表单
POST
方法 Json
传参;
一般我们有如下步骤:
实现ConverterFactory
接口
注册转换器
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class implements ConverterFactory <String , BaseEnum > { private static final Map<Class,Converter> CONVERTER_MAP=new HashMap<>(); public <T extends BaseEnum> Converter<String, T> getConverter (Class<T> aClass) { Converter converter=CONVERTER_MAP.get(aClass); if (converter==null ){ converter=new IntegerStrToEnumConverter<>(aClass); CONVERTER_MAP.put(aClass, converter); } return converter; } class IntegerStrToEnumConverter <T extends BaseEnum > implements Converter <String , T > { private Map<String,T> enumMap=new HashMap<>(); private IntegerStrToEnumConverter (Class<T> enumType) { T[] enums=enumType.getEnumConstants(); for (T e:enums){ enumMap.put(e.getCode()+"" ,e); enumMap.put(((Enum)e).name()+"" ,e); } } 大专栏 SpringBoot 处理 POST Json 传参枚举 "line"> public T convert (String source) { T result=enumMap.get(source); if (result==null ){ throw new IllegalArgumentException("No element matches " +source); } return result; } } }
但针对Json
传参,传递值时机会解析报错,可以通过设置 @JsonCreator
和 @JsonValue
来设定默认的反序列化方法. 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public enum PayChannelEnum implements BaseEnum<Integer> { ALIPAY(20 ), WECHARPAY(21 ); private Integer code; PayChannelEnum(int code) { this .code = code; } @JsonCreator public static PayChannelEnum create (String name) { try { return PayChannelEnum.valueOf(name); }catch (IllegalArgumentException e){ int code=Integer.parseInt(name); for (PayChannelEnum value : PayChannelEnum.values()) { if (value.code==code){ return value; } } } throw new IllegalArgumentException("No element matches " +name); } public void setCode (Integer code) { this .code = code; } public Integer getCode () { return code; } }
抽取范型,方便多种类型枚举
1 2 3 4 5 6 public interface BaseEnum<T> { @JsonValue T getCode(); }
经过改造,就可以支持所有场景的枚举解析。