Java Jackson反序列化接口枚举

时间:2018-10-24 15:40:15

标签: java json

我有给定的场景: 这是我正在实现的接口:

    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME
        property = "type")
    @JsonSubTypes({
        @JsonSubTypes.Type(value = MasterDevice.class, name = "COMPUTER"),
        @JsonSubTypes.Type(value = SlaveDevice.class, name = "FLASH_DRIVE"),
    })
    interface DeviceType{
        String getName();
    }

该接口由两个枚举使用:

public enum MasterDevice implements DeviceType{
    COMPUTER("Computer");
    private String name;
    public MasterDevice(String name){
       this.name=name;
     }
    @Override public String getName(){return this.name;}
}

第二个是针对可以连接到MasterDevice的设备的。

public enum SlaveDevice implements DeviceType{
     FLASH_DRIVE("USB Drive");
     private String name;
     public SlaveDevice(String name){
       this.name=name;
     }
     @Override public String getName(){return this.name;}
}

我要反序列化的POJO是:

public class DeviceInformation{
    private DeviceType type;
}

我想反序列化的json字符串如下:

String info = "{\"type\":\"COMPUTER\"}";
ObjectMapper mapper = new ObjectMapper();
DeviceInformation deviceInfo = mapper.readValue(info, DeviceInformation.class);

所有研究都建议为DeviceType实现自定义解串器,我不愿意这样做,因为它似乎很难维护。

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class DeviceType]: missing type id property '@type' (for POJO property 'type')`

似乎Jackson会在DeviceType上搜索类型属性,而该属性当然没有。如何告诉Jackson枚举选择基于枚举值(COMPUTER,FLASH_DRIVE)?

1 个答案:

答案 0 :(得分:0)

我认为您只是希望通过给一堆东西使用相同的字段和属性名称来折叠太多的关卡。

当前设置所需的JSON为:

String info = "{\"type\": {\"type\": \"COMPUTER\", \"COMPUTER\": null}}";

在此,外部“类型”用于DeviceInformation,内部“类型:COMPUTER”对用于MasterDevice的DeviceType多态性。最后的“计算机”是实例化MasterDevice.COMPUTER(这最后的怪异感觉就像是杰克逊实现中的一个错误)。

为了更清楚地说明正在发生的事情,这是一个简化的版本,并进行了一些重命名:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "type"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = MasterDevice.class, name = "MASTER"),
        @JsonSubTypes.Type(value = SlaveDevice.class, name = "SLAVE"),
})
interface DeviceType {
}

public enum MasterDevice implements DeviceType {
    LAPTOP, SERVER;
}

public enum SlaveDevice implements DeviceType {
    FLASH_DRIVE, WEBCAM;
}

public class DeviceInformation {
    public DeviceType deviceType;
}

然后:

String info = "{\"deviceType\": {\"type\": \"MASTER\", \"SERVER\": null}}";
ObjectMapper mapper = new ObjectMapper();
DeviceInformation deviceInfo = mapper.readValue(info, DeviceInformation.class));

如果您想要更精美的东西,则可能需要自定义序列化器。