使用Jackson反序列化枚举Shape.OBJECT失败

时间:2014-05-27 18:33:44

标签: java json serialization enums jackson

我有以下枚举声明:

@Document
@JsonFormat(shape= JsonFormat.Shape.OBJECT)
@JsonAutoDetect()
public enum Compass {
    north("Upper Center"),
    south("Lower Center"),
    east("Left Center"),
    west("Right Center"),
    ne("Upper Right"),
    nw("Upper Left"),
    se("Lower Right"),
    sw("Lower Left"),
    ;

    @JsonProperty   
    private String presentableName;
    @JsonProperty   
    private String name;

    private Compass() {}
    private Compass(String presentableName) {
        this.presentableName = presentableName;
    }

    public String getPresentableName() {
        return presentableName;
    }
    public void setPresentableName(String presentableName) {
        this.presentableName = presentableName;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @JsonCreator
    public static Compass fromObject(@JsonProperty("name") String name, @JsonProperty("presentableName") String presentableName) { 
        return Compass.sw;
    }
}

输入作为json对象到达,大部分都是正确反序列化的,但相关部分如下所示,其中placementCompass

{"placement":{"name":"se","presentableName":"Lower Right"}}

反序列化不起作用。我认为JsonCreator可以在这里工作,但出于某种原因,我得到了一个

  

org.springframework.web.HttpMediaTypeNotSupportedException:不支持内容类型'application / json; charset = UTF-8'

实际上只是反序列化失败的症状。

如果我将创作者更改为:

@JsonCreator
public static Compass fromObject(@JsonProperty("name") String name) { 
    return Compass.sw;
}

它变得更加奇怪,因为现在名称等于{而不是se(这看起来像json对象中的一个错误,但它是在一秒钟之前被反序列化的同一个对象所以它可能是OK)

我正在使用jackson 2.2.3,这是最新的。

2 个答案:

答案 0 :(得分:4)

如果将鼠标悬停在注释@JsonFormat上,则在其文本中明确指出Enums可以序列化,但如果您选择JsonFormat,则无法撤消它们。 Shape.Object。因此,如果您希望能够使用您的枚举来回,请不要使用此注释。希望以后能帮助你。

答案 1 :(得分:4)

虽然我仍然同意@Renatinn's answer,但我找到了解决此问题的方法(

只需创建一个@JsonCreator带注释的方法,即接收Map<String, Object>。 Jackson将复合对象反序列化为Map,并将其传递给方法:

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum TesterEnum {
    FirstValue(1, "One"),
    SecondValue(2, "Two");

    private int id;
    private String dsc;

    TesterEnum(int id, String dsc) {
        this.id = id;
        this.dsc = dsc;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getDsc(){
        return dsc;
    }
    public void setDsc(String dsc){
        this.dsc = dsc;
    }

    @JsonCreator
    public static TesterEnum fromObject(final Map<String, Object> obj) {
        if (obj != null && obj.containsKey("id")) {
            Integer id = null;
            if (obj.get("id") instanceof Integer) {
                id = (Integer)obj.get("id");
            } else {
                id = Integer.parseInt((String)obj.get("id"));
            }
            return fromId(id);
        }
        return null;
    }
    public static TesterEnum fromId(final Integer id) {
        if (id != null) {
            for (TesterEnum e : TesterEnum.values()) {
                if (id.equals(e.getId())) return e;
            }
        }
        return null;
    }
}

PS:你真的不需要fromId方法,它可以全部放入fromObject,但我在系统的其他部分使用第一个并且喜欢这种分离。< / p>

PS²:杰克逊通常会将id字段解码为Integer个实例,因此它会在if (obj.get("id") instanceof Integer)上输入fromObject,但我看到它被转换为String有时,这就是我正在检查的原因。