【问题标题】:Deserializing enum Shape.OBJECT using Jackson fails使用 Jackson 反序列化枚举 Shape.OBJECT 失败
【发布时间】:2014-07-16 18:56:36
【问题描述】:

我有以下枚举声明:

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

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

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

【问题讨论】:

  • 你能显示完整的堆栈跟踪吗?我只是在猜测,但可能是您误解了错误消息。

标签: java json serialization enums jackson


【解决方案1】:

如果您将鼠标悬停在注解 @JsonFormat 上,则在其文本中明确表示 Enum 可以序列化,但如果您选择 JsonFormat,则不能反转它们。形状.对象。因此,如果您希望能够在枚举中来回切换,请不要使用此注释。希望以后对你有帮助。

【讨论】:

    【解决方案2】:

    虽然我仍然同意@renatoaraujoc'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;
        }
    }
    

    P.S.:fromId这个方法你并不需要,可以全部放入fromObject,但是我在系统的其他部分使用第一个,喜欢这样分离。

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

    【讨论】:

    • 你能告诉我上面的代码是如何工作的吗?我的意思是为什么带有 Map 的代码有效,而另一个无效? @dinei
    • @RoyalTiger 抱歉,我不能。已经快三年了,我什至不再每天使用 C#。
    猜你喜欢
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2020-07-17
    • 1970-01-01
    • 2011-12-07
    相关资源
    最近更新 更多