Issue
Now I have a simple enum called AppName
:
package misc.enumn.app;
import lombok.Getter;
import misc.enumn.BaseEnum;
/**
* @author dolphin
*/
@Getter
public enum AppName implements BaseEnum {
CRUISE( 1, "cruise"),
BACK(2, "back"),
;
private Integer key;
private String value;
AppName(Integer key, String value) {
this.key = key;
this.value = value;
}
public void setKey(Integer key) {
this.key = key;
}
public void setValue(String value) {
this.value = value;
}
public static AppName getAppMarkByValue(String value) {
AppName datetimeType = null;
for (AppName type : AppName.values()) {
if (type.name().equals(value)) {
datetimeType = type;
}
}
return datetimeType;
}
public static AppName getAppMarkByKey(Short key) {
AppName datetimeType = null;
for (AppName type : AppName.values()) {
if (type.key.equals(key)) {
datetimeType = type;
}
}
return datetimeType;
}
}
then I define a request object like this:
@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserLoginRequest implements Serializable {
@ApiModelProperty(value = "app")
private AppName app;
}
when I passed appId 1 to the server side, the server parsed AppName as BACK
, I do not understand why it parsed as the BACK
not 'CRUISE'? I have already define the enum parser:
public class IntegerCodeToEnumConverterFactory implements ConverterFactory<Integer, BaseEnum> {
private static final Map<Class, Converter> CONVERTERS = Maps.newHashMap();
@Override
public <T extends BaseEnum> Converter<Integer, T> getConverter(Class<T> targetType) {
Converter<Integer, T> converter = CONVERTERS.get(targetType);
if (converter == null) {
converter = new IntegerToEnumConverter<>(targetType);
CONVERTERS.put(targetType, converter);
}
return converter;
}
}
and add to interceptor config:
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new IntegerCodeToEnumConverterFactory());
}
but seem still could not parse the enum, what should I do to make it parse the app correctly? this is the wrong parse(I want 1 parsed as CRUISE
and 2 parsed as BACK
):
By the way, when I replace the app from enum as Integer, it could parse it correctly(receive value 1). But I think using enum may be better for readable.
public class IntegerToEnumConverter <T extends BaseEnum> implements Converter<Integer, T> {
private Map<Integer, T> enumMap = Maps.newHashMap();
public IntegerToEnumConverter(Class<T> enumType) {
T[] enums = enumType.getEnumConstants();
for (T e : enums) {
enumMap.put(e.getKey(), e);
}
}
@Override
public T convert(Integer source) {
T t = enumMap.get(source);
if (ObjectUtils.isNull(t)) {
throw new IllegalArgumentException("");
}
return t;
}
}
Solution
what I am doing only support http get method, if you want to parse enum in http post method. define the code like this:
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AppName resolve(Integer key) {
return mappings.get(key);
}
this is my full code:
@Getter
public enum AppName implements BaseEnum {
CRUISE(1, "cruise"),
BACK(2, "back"),
;
@JsonValue
private Integer key;
private String value;
AppName(Integer key, String value) {
this.key = key;
this.value = value;
}
private static final Map<Integer, AppName> mappings;
static {
Map<Integer, AppName> temp = new HashMap<>();
for (AppName courseType : values()) {
temp.put(courseType.key, courseType);
}
mappings = Collections.unmodifiableMap(temp);
}
@EnumConvertMethod
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AppName resolve(Integer key) {
return mappings.get(key);
}
public void setKey(Integer key) {
this.key = key;
}
public void setValue(String value) {
this.value = value;
}
public static AppName getAppMarkByValue(String value) {
AppName datetimeType = null;
for (AppName type : AppName.values()) {
if (type.name().equals(value)) {
datetimeType = type;
}
}
return datetimeType;
}
public static AppName getAppMarkByKey(Short key) {
AppName datetimeType = null;
for (AppName type : AppName.values()) {
if (type.key.equals(key)) {
datetimeType = type;
}
}
return datetimeType;
}
}
Answered By - Dolphin