Jackson 在反序列化时忽略子类型 属性

Jackson ignore subtype property when deserialize

我在 Jackson 中使用子类型 属性,我想在反序列化 json 时使用此 属性。

package com.gaosoft.ai.kg.commons.sphinx.strategy;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.sankuai.ai.kg.commons.sphinx.model.FAQRecord;
import com.sankuai.ai.kg.commons.sphinx.model.FAQRequest;
import org.springframework.beans.factory.BeanFactory;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "strategyType"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = StrategyEmpty.class, name = "empty"),
        @JsonSubTypes.Type(value = StrategyNormal.class, name = "normal"),
        @JsonSubTypes.Type(value = StrategyDummy.class, name = "dummy")
}
)
public abstract class Strategy implements Serializable {

    private String strategyName;
    private String strategyType;
    private Map<String, Object> args = new HashMap<>();

    public String getStrategyType() {
        return strategyType;
    }

    public void setStrategyType(String strategyType) {
        this.strategyType = strategyType;
    }

    public Map<String, Object> getArgs() {
        return args;
    }

    public void setArgs(Map<String, Object> args) {
        this.args = args;
    }

    public String getStrategyName() {
        return strategyName;
    }

    public void setStrategyName(String strategyName) {
        this.strategyName = strategyName;
    }

    public abstract void init(BeanFactory beanFactory);

    public abstract List<FAQRecord> fetchFAQ(FAQRequest request);
}

正如我的代码所说,抽象 class 策略有 3 个子类型,我想在策略类型 属性 中保留子class 类型名称。 这样使用jackson时有没有办法填充strategyType?

(抱歉我的英语不好)

我想你要的是 @JsonTypeInfo#visible 属性:

Note on visibility of type identifier: by default, deserialization (use during reading of JSON) of type identifier is completely handled by Jackson, and is not passed to deserializers. However, if so desired, it is possible to define property visible = true in which case property will be passed as-is to deserializers (and set via setter or field) on deserialization.

所以在你的例子中,

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    property = "strategyType",
    visible = true
)

也就是说,这似乎是一种设计味道。可以将 StrategyEmptystrategyType 设置为 dummy 真的有效吗?如果不是,并且 StrategyEmpty 应该始终具有 emptystrategyType,那么为什么不只具有每个子类使用硬编码值实现的抽象 getStrategyType()