SpringBoot 處理 POST Json 傳參枚舉


在 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 異常。

日常開發中主要有如下幾種場景使用枚舉:

  1. GET 方法, 參數列表中有枚舉類型/自定義參數包含枚舉;
  2. POST 方法 Form表單
  3. POST 方法 Json傳參;

一般我們有如下步驟:

  1. 實現ConverterFactory接口
  2. 注冊轉換器

代碼:

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();

}

經過改造,就可以支持所有場景的枚舉解析。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM