【问题标题】:Jackson ignore subtype property when deserialize杰克逊在反序列化时忽略子类型属性
【发布时间】:2021-06-21 04:08:49
【问题描述】:

我在 Jackson 中使用了一个 subType 属性,我想在反序列化 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);
}

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

(对不起我的英语不好)

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    我认为您要的是 @JsonTypeInfo#visible 属性:

    关于类型标识符可见性的注意事项:默认情况下,类型标识符的反序列化(在读取 JSON 期间使用)完全由 Jackson 处理,并且不会传递给反序列化程序。但是,如果需要,可以定义属性 visible = true,在这种情况下,属性将在反序列化时按原样传递给反序列化器(并通过 setter 或字段设置)

    所以在你的例子中,

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

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

    【讨论】:

    • 我已经想到了。但是注释已经有了这些信息。我应该这样做,子类的信息是重复的。这也是一种难闻的气味:)(我写对了吗?我不是英语母语人士)
    • @Gao:我明白你在说什么。在这种情况下,我会说在 getter 中复制类型文字比允许 glass 的其他用户错误地设置类型要小得多。您还可以使用构造函数和 @JsonCreator 至少将其注入到 final 字段中并避免使用 setter。但是,当每个子类真正具有该属性的静态值时,它仍然支持广泛的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多