简体   繁体   中英

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

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

"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

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

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

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

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

"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 AnimalMixIn class, something like

@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 Jackson Object Mapper , note especially the mixIn method of Jackson2ObjectMapperBuilder

Using customized ObjectMapper within RestTemplate should be set through converters, something like

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM