Any way to skip deserialization of class members which are incompatible?

Viewed 30

I am calling an external API through RestTemplate. There is one parameter in the response structure that is dynamic i.e. returns two types of values, it returns a Json structure in the success case (status = true) and an empty string "" in case of failure (status = false). The RestTemplate is throwing exception in failure case as the string is not able to deserialze into the class object. This is my response class:

public class Response {
    private boolean status;
    private String message;
    private DynamicClass data;
}
public static class DynamicClass {
    private String id;
    private String createdDate;
}

This call is throwing exception:

ResponseEntity<Response> responseEntity = restTemplate.postForEntity(url, httpRequest, Response.class);

Exception:

org.springframework.web.client.RestClientException: Error while extracting response for type [class com.example.data.Response] and content type [application/json;charset=utf-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.example.data.Response$DynamicClass` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (''); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.example.data.Response$DynamicClass` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('')
 at [Source: (sun.net.www.protocol.http.HttpURLConnection$HttpInputStream); line: 1, column: 78] (through reference chain: com.example.data.Response["data"])
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:119)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:998)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:981)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
.
.
.
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.example.data.Response$DynamicClass` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (''); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.example.data.Response$DynamicClass` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('')
 at [Source: (sun.net.www.protocol.http.HttpURLConnection$HttpInputStream); line: 1, column: 78] (through reference chain: com.example.data.Response["data"])

Is there any way I can tell the parser to skip the deserialization of that member if it is not compatible as I don't need that empty string anyway? Or any other workaround for this problem?

1 Answers
  • Option 1::

If you are using Spring, the simplest way to override the default configuration is to define an ObjectMapper bean and to mark it as @Primary:

Check :: https://www.baeldung.com/spring-boot-customize-jackson-objectmapper

@Bean
@Primary
public ObjectMapper objectMapper() {

    return new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
      .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,true);

}
  • Option 2:: Convert the response to string and check for empty body and do the needful by converting the string to class object using object mapper.

    ResponseEntity responseEntity = restTemplate.postForEntity(url,httpRequest, String.class);

     if(!StringUtils.isBlank(responseEntity.getBody())) {
    
     Gson gson = new Gson();
     Response res= gson.fromJson(responseEntity.getBody(), Response .class);
    
     }
    
Related