【问题标题】:Generic Enum Json Deserialization通用枚举 Json 反序列化
【发布时间】:2017-04-18 06:17:53
【问题描述】:

我需要一个更好的休眠枚举映射,this 页面对我很有帮助(除了我使用 char 类型而不是 int)。

下一个问题是如何以通用方式序列化/反序列化枚举?

想想一个性别枚举:

@JsonSerialize(using = PersistentEnumSerializer.class)
@JsonDeserialize(using = PersistentEnumDeserializer.class)
public enum Gender implements PersistentEnum {

    MALE("M", "Male"), FEMALE("F", "Female");

    private String code;

    private String display;

    Gender(String code, String display) {
        this.code = code;
        this.display = display;
    }

    public String getName() {
        return name();
    }

    public String getCode() {
        return code;
    }

    public String getDisplay() {
        return display;
    }

    public String toString() {
        return display;
    }

}

它实现了 PersistentEnum 接口的 getName()、getCode() 和 getDisplay() 方法。序列化很容易:

public class PersistentEnumSerializer extends JsonSerializer<PersistentEnum> {

    @Override
    public void serialize(PersistentEnum object, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("name");
        generator.writeString(object.getName());
        generator.writeFieldName("code");
        generator.writeString(object.getCode());
        generator.writeFieldName("display");
        generator.writeString(object.getDisplay());
        generator.writeEndObject();
    }
}

但是如何在 java 6 中反序列化?在 java 8 中,我会向PersistentEnum 接口添加一个静态方法。

public class PersistentEnumDeserializer extends JsonDeserializer<PersistentEnum> {

    @Override
    public PersistentEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        //String value = node.get("name").asText();
        //TODO Somehow I need to get Gender.MALE if the json is {"name":"MALE","code":"M","display":"Male"}
        return null;
    }

}

【问题讨论】:

    标签: java json enums jackson


    【解决方案1】:

    一种可能的解决方案是向PersistentEnum 添加一个新方法getType(),它将识别Enum 的类型。

    @JsonSerialize(using = PersistentEnumSerializer.class)
    @JsonDeserialize(using = PersistentEnumDeserializer.class)
    public enum Gender implements PersistentEnum {
        @Override
        public String getType() {
            return "gender";
        }
    }
    

    还应修改序列化器以在序列化时包含类型。

    public class PersistentEnumSerializer extends JsonSerializer<PersistentEnum> {
    
    @Override
    public void serialize(PersistentEnum object, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("name");
        generator.writeString(object.getName());
        generator.writeFieldName("code");
        generator.writeString(object.getCode());
        generator.writeFieldName("display");
        generator.writeString(object.getDisplay());
        generator.writeFieldName("type");
        generator.writeString(object.getType());
        generator.writeEndObject();
    }
    }
    

    反序列化器可以写成如下所示。

        public class PersistentEnumDeserializer extends JsonDeserializer<PersistentEnum> {
    
        @Override
        public PersistentEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            JsonNode node = jp.getCodec().readTree(jp);
            return findEnum(node.get("type").asText(), node.get("name").asText());
        }
    
        private PersistentEnum findEnum(String type, String name) {
            switch (type) {
            case "gender":
                return Gender.valueOf(name);
            // handle other types here.
            default:
                return null;
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      虽然@Justin Jose 的解决方案不是我正在寻找的解决方案(因为我们需要将每个枚举添加到 findEnum 方法中),但它给了我一个很好的提示。 如果getType 是这样实现的:

      @Override
      public String getType() {
          return getClass().getSimpleName();
      }
      

      和这样的findEnum

      private PersistentEnum findEnum(String type, String name) {
          Class<?> c = null;
          try {
              c = Class.forName("enums." + type); //Assuming all PersistentEnum's are in "enums" package
              if (PersistentEnum.class.isAssignableFrom(c)) {
                  Method method = c.getMethod("name");
                  for (Object object : c.getEnumConstants()) {
                      Object enumName = method.invoke(object);
                      if (name.equals(enumName))
                          return (PersistentEnum) object;
                  }
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          return null;
      }
      

      它可能会起作用。未经测试,可能易受攻击。

      【讨论】:

        猜你喜欢
        • 2013-09-01
        • 1970-01-01
        • 2020-06-29
        • 1970-01-01
        • 2017-04-10
        • 1970-01-01
        • 2013-09-04
        • 1970-01-01
        • 2018-10-11
        相关资源
        最近更新 更多