通用Enum Json反序列化

时间:2017-04-18 06:17:54

标签: java json enums jackson

我需要一个更好的hibernate枚举映射,并且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;
    }

}

2 个答案:

答案 0 :(得分:1)

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

@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;
        }
    }

}

答案 1 :(得分:0)

虽然@Justin Jose的解决方案不是我想要的解决方案(因为对于我们需要添加到findEnum方法的每个枚举),它给了我一个很好的提示。 如果{new:true}实现如下:

getType

和findEnum这样

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

它可能有用。未经测试且可能易受攻击。