Java - 枚举转换器的通用摘要 class

Java - Generic abstract class for Enum Converter

我有一些枚举,它们是名称("String")和值("Integer")对,当前在每个枚举中我必须为 [= 实现一个@JsonCreator 方法36=]反序列化输入可以是名称或值

//User Enum
public enum UserType {
   StakeHolder(1),...

   private static final Map<String, UserType> helper = ImmutableMap.<String, UserType>builder()
            .put(String.valueOf(StakeHolder.getValue()), StakeHolder)
            .put(StakeHolder.name(), StakeHolder)
            .build();

   @JsonCreator
   public static UserType jsonDeserialize(String json) {
        return helper.get(json);
   }
}

//Role Enum
public enum RoleType {
   Admin(1),...

   private static final Map<String, RoleType> helper = ImmutableMap.<String, RoleType>builder()
            .put(String.valueOf(Admin.getValue()), Admin)
            .put(Admin.name(), Admin)
            .build();

   @JsonCreator
   public static RoleType jsonDeserialize(String json) {
        return helper.get(json);
   }
}

但我想知道是否有任何方法可以创建一个抽象 class 可以实现整体枚举,这是为了避免在我的每个枚举中始终实现类似的 "duplicate" 代码。当前代码就像

public abstract class JsonDeserializeEnum<E extends Enum<E>> {
  // protected Enum<E> myEnums;
  // private static final Map<String, E> myEnumHelper; ???

  public JsonDeserializeEnum() {
    super();
    // how to loop through myEnums to do something like
    // for(E iterator : myEnums.value()) not work...myEnums is not a collection of enums?
    // myEnumHelper.put(String.valueOf(iterator.getValue()), (E) iterator);
    // myEnumHelper.put(iterator.name, (E) iterator);
  } 

  @JsonCreator
   public static E jsonDeserialize(String json) {
        return myEnumHelper.get(json);
   }
}

//then
public enum UserType implements JsonDeserializeEnum<UserType>{
    StakeHolder(1),...
}
public enum RoleType implements JsonDeserializeEnum<RoleType>{
    Admin(1),...
}

我在这里遇到了两个挑战,

1) 我想在我的摘要 class 中有一个 init/constructor 可以将所有可用的枚举加载到静态映射中(仅一次),例如

调用UserType时,将所有用户类型枚举加载到静态映射中,然后从该映射反序列化;调用 RoleType 时,将所有角色类型枚举加载到映射中,然后从同一映射反序列化

2) 如果 No.1 不可能,没关系,假设我是否会在我的抽象 class 中删除地图,但仍然使用我的每个枚举中定义的地图,是否有无论如何,我的摘要 class 知道并可以使用我的 Enum 中定义的地图?

关键是要用一个JsonDeserializer。首先,您需要使用一个接口,以便能够对所有枚举使用相同的代码:

public interface ValueEnum {
    String name();
    int value();
}

并在每个枚举中实现它

public enum EnumExample implements ValueEnum {

    Hello(1),
    World(2);

    public final int value;

    private EnumExample(int value) {
        this.value = value;
    }

    @Override
    public int value() {
        return value;
    }
}

name() 已由枚举实现)

然后你可以将你的地图创建移动到一个单独的class(我使用java HashMap,你可以使用任何你喜欢的)

public class ValueEnumDeserializer<T extends ValueEnum> extends JsonDeserializer<T> {

    private final HashMap<String, T> map;

    public ValueEnumDeserializer(Class<T> c) {
        map = new HashMap<>();
        for (final T i : c.getEnumConstants()) {
            map.put(i.name(), i);
            map.put(String.valueOf(i.value()), i);
        }
    }

    @Override
    public T deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        return map.get(p.getText());
    }
}

然后当您创建对象映射器时,您必须通过反序列化器

    final ObjectMapper mapper = new ObjectMapper();
    final SimpleModule module = new SimpleModule();
    module.addDeserializer(EnumExample1.class, new ValueEnumDeserializer<>(EnumExample1.class));
    module.addDeserializer(EnumExample2.class, new ValueEnumDeserializer<>(EnumExample2.class));
    module.addDeserializer(EnumExample3.class, new ValueEnumDeserializer<>(EnumExample3.class));
    mapper.registerModule(module);