Jackson JsonTypeInfo.As.EXTERNAL_PROPERTY无法正常工作

时间:2013-09-12 06:57:56

标签: json polymorphism jackson

我正在使用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:缺少属性'type'   包含类型ID

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

2 个答案:

答案 0 :(得分:27)

来自Javadoc:

  

类似于PROPERTY的包含机制,但属性是   包括层次结构中的一级,即作为兄弟属性   与要输入的JSON对象相同的级别。请注意,此选项只能是   用于属性,不用于类型(类)。试着用它   类将导致基本PROPERTY的包含策略。

注意can only be used for properties以粗体显示。来源:JsonTypeInfo.As.EXTERNAL_PROPERTY

因此,您必须将Info类中的所有注释移至info类中的属性setInfoResponse方法。

@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属性。它将在序列化过程中动态生成。在反序列化中你不需要它,因为杰克逊关心类型。你的课可能是这样的:

class Response {

    private String status;
    private Info info;

    //getters, setters
}

另请参阅此问题:JSON nest class data binding

答案 1 :(得分:-1)

我找到的最简单的解决方案-将Json与类继承一起使用:

mapper.enableDefaultTyping();

然后,它将在json中为每个对象写入类名, 除非您希望在没有此类信息的情况下看起来漂亮,否则请使用以下解决方案。

这就是我的Json在不同对象的地图上的样子:

{
  "key" : [
    "com.types.SomeType",
    {
      "property1" : "a",
      "property2" : "b"
    }
  ]
}