Gao
Gao

Reputation: 952

Jackson ignore subtype property when deserialize

I'm using a subType property in Jackson, and I want to using this property when deserializing 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);
}

Like my code says, there are 3 subtype of abstract class Strategy, and I want to retain the subclass type name in strategyType property. Is there a way to fill strategyType when using jackson in this way?

(Sorry about my poor English)

Upvotes: 1

Views: 1479

Answers (1)

Mark Peters
Mark Peters

Reputation: 81164

I think what you're asking for is the @JsonTypeInfo#visible property:

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.

So in your example,

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

That said, this seems like a design smell. Is it truly valid that you can set a StrategyEmpty's strategyType to dummy? If not, and StrategyEmpty should always have a strategyType of empty, then why not just have an abstract getStrategyType() that each subclass implements with a hardcoded value?

Upvotes: 2

Related Questions