使用JsonTypeInfo.As.EXTERNAL_PROPERTY而不指定@JsonSubTypes

时间:2018-12-28 13:03:30

标签: java json jackson

是否可以使用@JsonTypeInfo.As.EXTERNAL_PROPERTY而不需要使用@JsonSubtypes指定子类型?

用例是我要创建通用的基类,该基类具有在其他项目中声明的不同主体。

公共基类,其中包含公共字段和正文

public class ApiModel<T extends ApiBodyModel> {

    private String modelType;
    private String version;
    private T body;

... getters / setters

}

抽象主体模型,该模型在内部具有进一步的共享上下文。

@JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "modelType")
//@JsonTypeIdResolver(InheritanceTypeIdResolver.class)
public abstract class ApiBodyModel<T extends ApiBodyModel<T>> {

    @JsonProperty
    private ApiContextModel context;

    public T withContext(ApiContextModel context) {
        this.context = context;
        return (T) this;
    }

... getters / setters

}

一个允许我放弃使用@JsonSubTypes的解决方案是使用Reflection获取抽象ApiBodyModel的所有子类型,详细信息在https://gist.github.com/root-talis/36355f227ff5bb7a057ff7ad842d37a3处进行,但是仍然需要使用类名来被声明在体内,而不是向上一级。

发现使用@JsonTypeInfo.As.EXTERNAL_PROPERTY的示例声明了JsonSubTypes,但是我想避免这样做,因为抽象类将在一个普通项目中。

1 个答案:

答案 0 :(得分:0)

我通过让顶级类使用InheritanceTypeIdResolver来解决此问题

公共基类,其中包含公共字段和正文

@JsonTypeInfo(use = Id.CUSTOM, property = "modelType", visible = true)
@JsonTypeIdResolver(InheritanceTypeIdResolver.class)
public abstract class ApiModel<T extends ApiBodyModel> {

    private String modelType;
    private String version;

    public abstract T getBody();

    public abstract void setBody(T body);

}

抽象主体模型,该模型在内部具有进一步的共享上下文。

public abstract class ApiBodyModel {

    private ApiContextModel context;

}

具体的基类实现

public class ConcreteModel extends ApiModel<ConcreteBody> {

    public static final String MODEL_TYPE = "concreteModel";

    private ConcreteBody body;

    public ConcreteModel(
        String version,
        ConcreteBody body) {
        super(MODEL_TYPE, version);
        this.body = body;
    }
}

具体实施

public class ConcreteBody extends ApiBodyModel {

    private String source;

    public ConcreteBody(ApiContextModel context, String source) {
        super(context);
        this.source = source;
    }
}