首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用@JsonTypeInfo和@JsonSubTypes,在没有基类和类型信息的情况下反序列化具体子类的对象

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

Stack Overflow用户
提问于 2021-03-29 04:39:34
回答 2查看 1.8K关注 0票数 1

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

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

代码语言:javascript
运行
复制
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import 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")
})
public abstract class Animal {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

和一个Dog子类:

代码语言:javascript
运行
复制
public class Dog extends Animal {
    private String breed;

    public Dog() {
    }

    public Dog(String name, String breed) {
        setName(name);
        setBreed(breed);
    }

    public String getBreed() {
        return breed;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }
}

我知道可以基于其父类实例化一个子类对象,如下所示:

代码语言:javascript
运行
复制
{
    "type": "Dog",
    "name": "Jack",
    "breed": "shepherd"
}
代码语言:javascript
运行
复制
Animal deserializedDog = objectMapper.readValue(dogJson, Animal.class);

但是,有时我想直接实例化子类对象,而不使用父类:

代码语言:javascript
运行
复制
{
    "name": "Jack",
    "breed": "shepherd"
}
代码语言:javascript
运行
复制
Dog deserializedDog = objectMapper.readValue(dogJson, Dog.class);

子类对象将被发送到端点:

代码语言:javascript
运行
复制
@PostMapping("/endpoint")
    public ResponseEntity<Dog> sendDataToJms(
            @RequestBody Dog request, @RequestHeader Map<String, String> headers) throws Exception {
    //...
}

有可能吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-30 04:53:08

我找到了解决办法。

您需要启用MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL,以便使用没有类型信息的具体子类直接反序列化对象。

根据官方文件,

MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL是一种功能,它指定如果没有通过@JsonTypeInfo.defaultImpl注释指定显式默认类,则是否将声明的多态值的基类型用作“默认”实现。

接下来,您需要自定义将JSON请求转换为Java的MappingJackson2HttpMessageConverter,如下所示。

代码语言:javascript
运行
复制
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL);
    jsonConverter.setObjectMapper(objectMapper);
    return jsonConverter;
}
票数 1
EN

Stack Overflow用户

发布于 2021-03-29 06:05:46

您只需要像这样创建ObjectMapper

代码语言:javascript
运行
复制
ObjectMapper objectMapper = new ObjectMapper()
                .addHandler(new DeserializationProblemHandler() {
                    @Override
                    public JavaType handleMissingTypeId(DeserializationContext ctxt,
                                                        JavaType baseType,
                                                        TypeIdResolver idResolver,
                                                        String failureMsg)
                            throws IOException {
                        return baseType;
                    }
                });
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66848837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档