Java:在 json -SpringBoot 中使用“@class”将 json 反序列化为对象在休息模板中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30527640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:17:06  来源:igfitidea点击:

Java: Deserialize a json to object in rest template using "@class" in json -SpringBoot

javaHymansonspring-bootdeserializationresttemplate

提问by Karthik Pala

I have to instantiate a class which extends the abstract class from JSON using information in @class as shown below.

我必须实例化一个类,该类使用@class 中的信息从 JSON 扩展抽象类,如下所示。

"name": {
  "health": "xxx",
  "animal": {
    "_class": "com.example.Dog",
    "height" : "20"
    "color" : "white"
  }
},

Here the abstract class is animal and dog extends the animal class. So using the information in @class, can we instantiate dog directly. Also this is the response I am getting in restTemplate

这里的抽象类是动物,狗扩展了动物类。那么利用@class中的信息,我们可以直接实例化dog吗?这也是我在 restTemplate 中得到的响应

ResponseEntity<List<SomeListName>> response = restTemplate.exchange("http://10.150.15.172:8080/agencies", HttpMethod.GET, request, responseType);

The following error is coming when this line is executed. Since the POJO classes are auto-generated, I cannot use annotations like @JsonTypeInfo

执行此行时出现以下错误。由于 POJO 类是自动生成的,我不能使用像@JsonTypeInfo这样的注释

I am using Spring boot and maven. This error is coming in console.

我正在使用 Spring Boot 和 maven。此错误出现在控制台中。

Could not read JSON: Can not construct instance of "MyPOJO", problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information

无法读取 JSON:无法构造“MyPOJO”的实例,问题:抽象类型要么需要映射到具体类型,要么具有自定义反序列化器,要么使用附加类型信息进行实例化

回答by Master Slave

You can use @JsonTypeInfoannotation regardless of the fact that the classes are generated, by adhering to MixIn's

@JsonTypeInfo无论类是否生成,您都可以使用注释,通过遵守MixIn 的

"mix-in annotations are": a way to associate annotations with classes, without modifying (target) classes themselves.

That is, you can:

Define that annotations of a mix-in class (or interface) will be used with a target class (or interface) such that it appears as if the target class had all annotations that the mix-in class has (for purposes of configuring serialization / deserialization)

“混合注释是”:一种将注释与类相关联的方法,而无需修改(目标)类本身。

也就是说,您可以:

定义混合类(或接口)的注解将与目标类(或接口)一起使用,这样它看起来就好像目标类具有混合类具有的所有注解(用于配置序列化/反序列化)

So you can write your AnimalMixInclass, something like

所以你可以写你的AnimalMixIn类,比如

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "_class")  
@JsonSubTypes({  
    @Type(value = Cat.class, name = "com.example.Cat"),  
    @Type(value = Dog.class, name = "com.example.Dog") })  
abstract class AnimalMixIn  
{  

}  

and configure your deserializer

并配置您的解串器

    ObjectMapper mapper = new ObjectMapper();  
    mapper.getDeserializationConfig().addMixInAnnotations(  
    Animal.class, AnimalMixIn.class);

Since you're using Spring Boot, you can check the following blog post to see how you can customize the ObjectMapper for using the MixIns, Customizing the Hymanson Object Mapper, note especially the mixInmethod of Hymanson2ObjectMapperBuilder

由于您使用的是 Spring Boot,您可以查看以下博客文章以了解如何自定义 ObjectMapper 以使用 MixIns,Customizing the Hymanson Object Mapper,尤其要注意的mixIn方法Hymanson2ObjectMapperBuilder

Using customized ObjectMapperwithin RestTemplateshould be set through converters, something like

使用自定义ObjectMapperRestTemplate应通过转换器设置,例如

    RestTemplate restTemplate = new RestTemplate();
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    MappingHymanson2HttpMessageConverter jsonMessageConverter = new MappingHymanson2HttpMessageConverter();
    jsonMessageConverter.setObjectMapper(objectMapper);
    messageConverters.add(jsonMessageConverter);
    restTemplate.setMessageConverters(messageConverters);
    return restTemplate;