Jackson JsonTypeInfo.As.EXTERNAL_PROPERTY 无法按预期工作

问题描述 投票:0回答:2

我正在使用 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的理解有误?

json polymorphism jackson
2个回答
62
投票

来自 Javadoc:

类似于PROPERTY的包含机制,只不过property是 包括层次结构中的更高一级,即作为同级属性 与要输入的 JSON 对象级别相同。注意这个选择只能是 用于属性,而不是类型(类)。尝试将其用于 课程将导致基本 PROPERTY 的包容策略。

注意到

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

因此,您必须将所有注释从

Info
类移动到
info
属性或
setInfo
类中的
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 嵌套类数据绑定


0
投票

对于所有使用 AutoValue 或任何其他 源代码生成器 的人:当您注释抽象方法(在生成的代码中返回实际属性)时,@JsonTypeInfo@JsonSubTypes 注释不起作用。 如果你这样做,你会得到以下异常:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of [xxx] (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

当您在注释为 @JsonCreator 的方法中注释参数时,它也不起作用。如果你这样做,你会得到这个奇怪的异常:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class [xxx]

因此,要处理它,只需不要使用此类的源代码生成器,只需使用常见的杰克逊注释映射

Response
对象:@JsonCreator,@JsonProperty@JsonTypeInfo,@JsonSubTypes

使用 Jackson 2.10.5 进行测试

© www.soinside.com 2019 - 2024. All rights reserved.