【问题标题】:Java Jackson deserialize interfacing enumsJava Jackson 反序列化接口枚举
【发布时间】:2018-10-24 15:40:14
【问题描述】:

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

    @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 Enum 选择是基于枚举值(COMPUTER、FLASH_DRIVE)?

【问题讨论】:

  • 能否同时包含您的 getName() 实现和反序列化代码?
  • @DaneWhite 我包含了它。
  • 您的代码仍然与出现的异常不匹配。异常表明您没有在 JsonTypeInfo 中指定 property = "type",因为它默认为 "@type"。

标签: java json


【解决方案1】:

我认为您期望通过为一堆事物提供相同的字段和属性名称来折叠太多级别。

当前设置所需的 JSON 为:

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

这里,外层的“type”用于DeviceInformation,内层的“type: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));

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

【讨论】:

  • 好吧,所以我误解了JsonTypeInfo的用法。我不敢相信我是唯一一个想做那种事情的人......
  • 我只是塞进了一个自定义的反序列化器,迭代两个枚举并进行比较。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 2015-10-19
  • 2012-02-06
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
  • 2020-07-17
相关资源
最近更新 更多