将超类json反序列化为子类对象

时间:2018-10-31 09:49:26

标签: json jackson

我的软件主要围绕rfid设备旋转。所有这些设备都具有(大部分)相同的配置选项,例如天线应以何种功率设置传输。但是,每个阅读器随附的API在设置天线功率方面有所不同。阅读器的配置在中央服务器上完成,并保存为json字符串。我正在尝试提出一种方法,使其具有通用的json字符串来配置天线功率(例如),而不必为每个API进行自定义。这就是我要实现的目标。

用于设置天线功率的json字符串类似于:

{"power":30}

我用于配置电源的超类:

public abstract class SetPower<T> {
    protected int power;

    public SetPower(int power) {
        this.power = power;
    }

    public abstract void configure(T rfidReader);
}

用于配置CompanyX读取器电源的子类:

public class CompanyXSetPower extends SetPower<CompanyXReader> {

    @JsonCreator
    public CompanyXSetPower(@JsonProperty("power") int power) {
        super(power);
    }

    @Override
    public void configure(CompanyXReader reader) {
        reader.setPower((byte) power);
    }
}

用于配置CompanyY读取器电源的子类:

public class CompanyYSetPower extends SetPower<CompanyYReader> {

    @JsonCreator
    public CompanyYSetPower(@JsonProperty("power") int power) {
        super(power);
    }

    @Override
    public void configure(CompanyYReader reader) {
        reader.setOutputPower(power);
    }
}

什么是将通用json反序列化为特定子类而不必向json字符串指定特定类详细信息的“最佳”方法是什么。我可以在json字符串中包含超类详细信息,因为需要某种方法来标识json数据的对象类型。

1 个答案:

答案 0 :(得分:0)

您想要的被称为将JSON反序列化为多态类型。 (有关类似问题,请参见this question)。

您将需要在JSON内容中添加其他类型属性, 这样{"type":"x","power":30}就可以反序列化 放入CompanyXSetPower对象中, 并且{"type":"y","power":30}被反序列化 放入CompanyYSetPower对象中。

为此,您需要使用以下方法增强抽象基类SetPower @JsonTypeInfo@JsonSubTypes注释,以便Jackson可以 了解有关JSON与您的各种Java类之间的映射的足够信息。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = CompanyXSetPower.class, name = "x"),
    @JsonSubTypes.Type(value = CompanyYSetPower.class, name = "y")
})
public abstract class SetPower<T> {
    protected int power;

    public SetPower(int power) {
        this.power = power;
    }

    public abstract void configure(T rfidReader);
}

反序列化可以简单地通过以下方式完成:

ObjectMapper objectMapper = new ObjectMapper();
SetPower<?> setPower = objectMapper.readValue(url, SetPower.class);