Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.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 使用@JsonTypeInfo和@JsonSubTypes,反序列化没有基类和类型信息的具体子类的对象_Java_Spring Boot_Rest_Jackson_Polymorphism - Fatal编程技术网

Java 使用@JsonTypeInfo和@JsonSubTypes,反序列化没有基类和类型信息的具体子类的对象

Java 使用@JsonTypeInfo和@JsonSubTypes,反序列化没有基类和类型信息的具体子类的对象,java,spring-boot,rest,jackson,polymorphism,Java,Spring Boot,Rest,Jackson,Polymorphism,使用@JsonTypeInfo和@JsonSubTypes,可以反序列化没有类型信息的具体子类的对象吗 假设我有一个抽象的Animal类: import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 导入com.fasterxml.jackson.annotation.JsonSubTypes; 导入com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonIgnorePropertie

使用
@JsonTypeInfo
@JsonSubTypes
,可以反序列化没有类型信息的具体子类的对象吗

假设我有一个抽象的
Animal
类:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
导入com.fasterxml.jackson.annotation.JsonSubTypes;
导入com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonIgnoreProperties(ignoreUnknown=true)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.PROPERTY,PROPERTY=“type”)
@JsonSubTypes({
@JsonSubTypes.Type(value=Dog.class,name=“Dog”),
@JsonSubTypes.Type(value=Cat.class,name=“Cat”)
})
公共抽象类动物{
私有字符串名称;
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
}
子类:

公共类狗扩展了动物{
私家犬;
公犬(){
}
公犬(犬种名称、犬种){
集合名(名称);
芦苇(品种);
}
公共字符串getbride(){
回归品种;
}
公共芦苇(弦品种){
这个品种;
}
}
我知道我可以根据父类实例化子类对象,如下所示:

ObjectMapper objectMapper = new ObjectMapper()
                .addHandler(new DeserializationProblemHandler() {
                    @Override
                    public JavaType handleMissingTypeId(DeserializationContext ctxt,
                                                        JavaType baseType,
                                                        TypeIdResolver idResolver,
                                                        String failureMsg)
                            throws IOException {
                        return baseType;
                    }
                });
{
“类型”:“狗”,
“姓名”:“杰克”,
“品种”:“牧羊人”
}
Animal反序列化ddog=objectMapper.readValue(dogJson,Animal.class);
但是,有时我想直接实例化子类对象,而不使用父类:

{
“姓名”:“杰克”,
“品种”:“牧羊人”
}
Dog反序列化ddog=objectMapper.readValue(dogJson,Dog.class);
子类对象将被发送到端点:

@PostMapping(/endpoint)
公共响应发送数据到JMS(
@RequestBody狗请求,@RequestHeader映射头)引发异常{
//...
}

有可能吗?

您只需要像这样创建
ObjectMapper

ObjectMapper objectMapper = new ObjectMapper()
                .addHandler(new DeserializationProblemHandler() {
                    @Override
                    public JavaType handleMissingTypeId(DeserializationContext ctxt,
                                                        JavaType baseType,
                                                        TypeIdResolver idResolver,
                                                        String failureMsg)
                            throws IOException {
                        return baseType;
                    }
                });

我找到了解决办法

您需要启用
MapperFeature。使用\u BASE\u TYPE\u作为\u DEFAULT\u IMPL
以使用具体的子类直接反序列化对象,而不使用类型信息

根据官方文件,

MapperFeature.使用\u BASE\u TYPE\u作为\u DEFAULT\u IMPL
是 指定多态值的声明基类型是否为 如果没有显式的默认类,则用作“默认”实现 通过
@JsonTypeInfo.defaultImpl
注释指定

接下来,您需要定制将JSON请求转换为Java对象的
MappingJackson2HttpMessageConverter
,如下所示

@Bean
公共映射Jackson2HttpMessageConverter映射Jackson2HttpMessageConverter(){
MappingJackson2HttpMessageConverter jsonConverter=新的MappingJackson2HttpMessageConverter();
ObjectMapper ObjectMapper=新的ObjectMapper();
objectMapper.enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL);
setObjectMapper(objectMapper);
返回jsonConverter;
}

尝试时发生了什么?如果忽略
类型
字段:
JSON解析错误:在尝试解析…
的子类型时缺少类型id,那么当您显式提供
Dog.class
时,您不应该得到它。是的,您是对的。JSON对象在
@PostMapping
注释下作为
@RequestBody Dog
传递时被反序列化。但是,我确实提供了子类名称,它不会自动使用
Dog.class
吗?是否提供了子类名称Where/how?您的问题没有包含足够的详细信息,无法回答。代码做什么?当ObjectMapper没有看到
type
字段时,它将尝试
DeserializationProblemHandler
来处理缺少的类型id,因此您可以添加一个新的
DeserializationProblemHandler
来返回所需的
JavaType
,我使用的是jackson 2.9.4,它没有
MapperFeature。使用\u BASE\u TYPE\u作为\u DEFAULT\u IMPL