34

我正在使用 Jackson 来解析我无法控制的 JSON。JSON 看起来像这样:

{
    "status":"0"
    "type":"type1"
    "info": {
       // additional fields
    }
}

我的课看起来像这样

public class Response {
    private String status;
    private String type;
    private Info info
}

我使用的 Info 的子类取决于 type 属性,所以我的 info 映射是

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = {
        @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
        @JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public abstract class Info {
    // some fields
}

据我所知,当区分元素与必须转换的元素处于同一级别时,这是使用类型信息的正确方法。但这不起作用,我总是得到同样的错误:

com.fasterxml.jackson.databind.JsonMappingException:意外令牌(END_OBJECT),预期 FIELD_NAME:缺少包含类型 ID 的属性“类型”

如果我将 EXTERNAL_PROPERTY 更改为 PROPERTY,我仍然会收到相同的错误。我对 EXTERNAL_PROPERTY 的理解错了吗?

4

1 回答 1

50

来自 Javadoc:

包含机制类似于 PROPERTY,除了属性在层次结构中包含更高一级,即作为与 JSON 对象相同级别的兄弟属性来键入。请注意,此选项只能用于属性,不能用于类型(类)。尝试将其用于类将导致基本属性的包含策略。

注意到can only be used for properties是粗体的。来源:JsonTypeInfo.As.EXTERNAL_PROPERTY

因此,您必须将所有注释从Info类移动到类中的属性infosetInfo方法Response

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = { @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
        @JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public void setInfo(Info info) {
    this.info = info;
}

对我来说,您还应该从课程中删除type财产。Response它将在序列化过程中动态生成。在反序列化中你不需要它,因为 Jackson 关心类型。您的课程可能如下所示:

class Response {

    private String status;
    private Info info;

    //getters, setters
}

另请参阅此问题:JSON 嵌套类数据绑定

于 2014-01-03T23:28:28.860 回答