简体   繁体   English

Java Jackson反序列化接口枚举

[英]Java Jackson deserialize interfacing enums

I have the given situtation: This is the interface I am implementing: 我有给定的场景:这是我正在实现的接口:

    @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();
    }

The interface is used by two enums: 该接口由两个枚举使用:

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

The second one is for devices you can attach to the MasterDevice . 第二个是针对可以连接到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;}
}

The POJO that I want to deserialize is: 我要反序列化的POJO是:

public class DeviceInformation{
    private DeviceType type;
}

And the json String I want to deserialize look like this: 我想反序列化的json字符串如下所示:

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

All research was proposing implementing a custom deserializer for the DeviceType which I am not keen to do since it seems so bad to maintain. 所有研究都建议为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')`

It seems like Jackson searches for an type property on the DeviceType which of course it does not have. 似乎Jackson会在DeviceType上搜索类型属性,而该属性当然没有。 How do I tell Jackson that the Enum selection is based on the enum value (COMPUTER, FLASH_DRIVE)? 我如何告诉Jackson枚举选择基于枚举值(COMPUTER,FLASH_DRIVE)?

I think you're expecting too many levels to be collapsed for you simply by giving a bunch of things the same field and property names. 我认为您只是希望通过给一堆东西使用相同的字段和属性名称来折叠太多级别。

The JSON required for your current setup would be: 当前设置所需的JSON为:

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

Here, the outer "type" is for DeviceInformation, the inner "type:COMPUTER" pair are for DeviceType polymorphism of MasterDevice. 在此,外部“类型”用于DeviceInformation,内部“类型:COMPUTER”对用于MasterDevice的DeviceType多态性。 And the final "COMPUTER" is to instantiate MasterDevice.COMPUTER (this last bit of weirdness feels like a bug with the Jackson implementation). 最后的“计算机”是实例化MasterDevice.COMPUTER(这最后的怪异感觉就像杰克逊实现中的一个错误)。

To make it more obvious what's going on, here's a simplified version with some renaming: 为了更清楚地说明正在发生的事情,这是一个简化的版本,带有一些重命名:

@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;
}

Then: 然后:

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

If you want something more elegant, then you'll likely need a custom serializer. 如果您想要更精美的东西,则可能需要自定义序列化程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM