簡體   English   中英

Java - 用於枚舉轉換器的通用抽象 class

[英]Java - Generic abstract class for Enum Converter

我有一些枚舉,它們是 name("String") 和 value("Integer") 對,當前在每個枚舉中我必須為 Json 實現一個 @JsonCreator 方法反序列化,輸入可以是名稱或值

//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,這是為了避免在我的每個枚舉中始終實現類似的“重復”代碼。 當前的代碼就像

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 中有一個初始化/構造函數,它可以將所有可用的枚舉加載到 static 映射中(僅一次),例如,

調用UserType時,將所有用戶類型枚舉加載到 static map 中,然后從該 map 反序列化; 調用RoleType時,將所有角色類型枚舉加載到 map 中,然后從相同的 map 反序列化

2) If No.1 is not possible, it's Ok, Let's say if I will get rid of the map in my abstract class, but still use map defined in each of my Enum, is there anyway that my abstract class know and can use我的枚舉中定義的 map?

關鍵是使用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()已經由 Enum 實現)

然后您可以將您的 map 創建移動到單獨的 class(我使用 java Z063A5BC4701661C3CABZEBCE,您可以使用任何您喜歡的東西)

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

然后當您創建 object 映射器時,您必須通過解串器

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM