有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

json Java Jackson反序列化接口枚举

我有给定的情况: 这是我正在实现的接口:

    @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上搜索类型属性,而DeviceType当然没有。如何告诉Jackson枚举选择基于枚举值(计算机、闪存驱动器)


共 (1) 个答案

  1. # 1 楼答案

    我认为,仅仅通过给一堆东西提供相同的字段和属性名称,您就期望有太多的级别被折叠

    当前设置所需的JSON为:

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

    这里,外部的“type”表示设备信息,内部的“type:COMPUTER”对表示主设备的DeviceType多态性。最后一个“计算机”是实例化主设备。计算机(这最后一点奇怪感觉就像是Jackson实现中的一个bug)

    为了更清楚地了解发生了什么,这里有一个简化版本,其中包含一些重命名:

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

    如果您想要更优雅的东西,那么您可能需要一个自定义序列化程序