在 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(); }
經過改造,就可以支持所有場景的枚舉解析。