Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson的多态反序列化问题_Java_Json_Jackson_Deserialization_Json Deserialization - Fatal编程技术网

Java Jackson的多态反序列化问题

Java Jackson的多态反序列化问题,java,json,jackson,deserialization,json-deserialization,Java,Json,Jackson,Deserialization,Json Deserialization,我有以下几个类,我想使用Jackson反序列化JSON字符串 PushNotificationMessage.java public class PushNotificationMessage { @JsonProperty("device_info") private DeviceInfo deviceInfo; private String content; //getters & setters } public class DeviceInfo

我有以下几个类,我想使用Jackson反序列化JSON字符串

PushNotificationMessage.java

public class PushNotificationMessage {
    @JsonProperty("device_info")
    private DeviceInfo deviceInfo;
    private String content;

    //getters & setters
}
public class DeviceInfo {

    @JsonProperty(value = "device_type")
    private String deviceType;

    //getters & setters
}
public class IOSDeviceInfo extends DeviceInfo {

    @JsonProperty(value = "device_id")
    private String deviceId;
    private String arn;
    @JsonProperty(value = "user_data")
    private String userData;

    //getters & setters
}
public class WebDeviceInfo extends DeviceInfo {
    private String endpoint;
    private String key;
    private String auth;

    //getters & setters
}
DeviceInfo.java

public class PushNotificationMessage {
    @JsonProperty("device_info")
    private DeviceInfo deviceInfo;
    private String content;

    //getters & setters
}
public class DeviceInfo {

    @JsonProperty(value = "device_type")
    private String deviceType;

    //getters & setters
}
public class IOSDeviceInfo extends DeviceInfo {

    @JsonProperty(value = "device_id")
    private String deviceId;
    private String arn;
    @JsonProperty(value = "user_data")
    private String userData;

    //getters & setters
}
public class WebDeviceInfo extends DeviceInfo {
    private String endpoint;
    private String key;
    private String auth;

    //getters & setters
}
IOSDeviceInfo.java

public class PushNotificationMessage {
    @JsonProperty("device_info")
    private DeviceInfo deviceInfo;
    private String content;

    //getters & setters
}
public class DeviceInfo {

    @JsonProperty(value = "device_type")
    private String deviceType;

    //getters & setters
}
public class IOSDeviceInfo extends DeviceInfo {

    @JsonProperty(value = "device_id")
    private String deviceId;
    private String arn;
    @JsonProperty(value = "user_data")
    private String userData;

    //getters & setters
}
public class WebDeviceInfo extends DeviceInfo {
    private String endpoint;
    private String key;
    private String auth;

    //getters & setters
}
WebDeviceInfo.java

public class PushNotificationMessage {
    @JsonProperty("device_info")
    private DeviceInfo deviceInfo;
    private String content;

    //getters & setters
}
public class DeviceInfo {

    @JsonProperty(value = "device_type")
    private String deviceType;

    //getters & setters
}
public class IOSDeviceInfo extends DeviceInfo {

    @JsonProperty(value = "device_id")
    private String deviceId;
    private String arn;
    @JsonProperty(value = "user_data")
    private String userData;

    //getters & setters
}
public class WebDeviceInfo extends DeviceInfo {
    private String endpoint;
    private String key;
    private String auth;

    //getters & setters
}
我想反序列化以下JSON内容:

{
    "device_info": {
        "endpoint": "https://android.googleapis.com/gcm/send/blah",
        "key": "blahkey",
        "auth": "blahauth",
        "device_type": "web"
    },
    "content": "Notification content"
}
我只是简单地使用
ObjectMapper
来尝试执行反序列化

final ObjectMapper objectMapper = new ObjectMapper();
final PushNotificationMessage message = objectMapper.readValue(jsonString, PushNotifictionMessage.class);
当我这样做时,我得到:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:无法识别的字段“endpoint”(class com.blah.DeviceInfo),未标记为可忽略(一个已知属性:“device_type”])

我如何让Jackson认识到它需要映射到
WebDeviceInfo
实例,而不是尝试将其映射到没有
端点
字段的
DeviceInfo
超类

我曾尝试在不同的类中使用
@JsonTypeInfo
@JsonSubTypes
注释,但我找不到如何使用它们的好例子

EDIT:我在我的
DeviceInfo
类中添加了
@jsondeseserialize(使用=DeviceInfoDeserializer.class)
注释,并创建了以下
DeviceInfoDeserializer

public class DeviceInfoDeserializer extends JsonDeserializer<DeviceInfo> {

    private static final String DEVICE_TYPE = "device_type";
    private static final String WEB = "web";
    private static final String IOS = "ios";

    @Override
    public DeviceInfo deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException {
        final ObjectMapper objectMapper = (ObjectMapper) jsonParser.getCodec();
        final ObjectNode root = objectMapper.readTree(jsonParser);
        if (root.has(DEVICE_TYPE)) {
            final JsonNode jsonNode = root.get(DEVICE_TYPE);
            if (jsonNode.asText().equalsIgnoreCase(WEB)) {
                return objectMapper.readValue(root.toString(), WebDeviceInfo.class);
            } else if (jsonNode.asText().equalsIgnoreCase(IOS)) {
                return objectMapper.readValue(root.toString(), IOSDeviceInfo.class);
            }
        }
        throw deserializationContext.mappingException("Failed to de-serialize device info, as device_type was not \"web\" or \"ios\"");
    }
}

编辑:只需将
@jsondeservialize(as=WebDeviceInfo.class)
@jsondeservialize(as=IOSDeviceInfo.class)
添加到我的子类中,现在它可以正常工作了。非常感谢。

Jackson没有意识到多态性,它只是尝试创建一个具体DeviceInfo类的实例

但是,您可以实现一个自定义反序列化程序,该程序以编程方式解析设备信息JSON,并知道由于某些字段(如
端点
)的唯一性,何时实例化其中一个子类


这里可以找到一个例子:

@jsondeseligate(as=IOSDeviceInfo.class)
@jsondeseligate(as=WebDeviceInfo.class)
注释的子类是否与示例中一样?是的,这就是问题所在。谢谢,这正是我想要的。