Spring RestTemplate and JSON how to ignore empty Arrays deserialization?

时间:2015-07-31 19:24:25

标签: arrays json spring deserialization resttemplate

I am currently using Spring 4.1.6 with a RestTemplate to consume a third party webservice with JSON which I cannot change its behavior.I am using Jackson databind v2.6.0.

Problem: Sometimes the service returns for a member a hashmap {member:{"key":"value",...}} sometimes the same member is just an empty array {member:[]}. So I can not ignore the property by default.

Is there a way to configure the deserialization to ignore empty arrays? I saw a jackson property "WRITE_EMPTY_JSON_ARRAYS" but I am not quite sure how I can use it with my restTemplate and spring configuration.

Are there other possiblities e.g. use some combination of @JsonXXX Annotations? I saw @JsonSerialize which can be used on class level, but I don't like to write a deserializer for all my classes just to handle this situation (However if there is no other way of course I will do)

Example responses to llustrate the behavior of the service:

  • response with a hashmap {"id":170,"categories":{"13":"caro"}}

  • response with empty array of the same member {"id":170,"categories":[]}

Example of my RestTemplate usage:

    BasicAuthRequestFactory requestFactory = new BasicAuthRequestFactory(httpClient);        
    restTemplate = new RestTemplate(requestFactory);
    Article a = restTemplate.getForObject(new URI("http://..."), Article.class);

Error:

 caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token
 at [Source: java.io.PushbackInputStream@4aa21f9d; line: 1, column: 1456] (through reference chain: ResponseArticleWrapper["data"]->Article["categories"])
 at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)

Example of my current annotated class:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public class Article {  
    @JsonProperty("id")
    private Integer id;
    @JsonProperty("categories")  
    private Map<Integer,String> categories = new HashMap<Integer,String>();
}

Thank you in advance for any hints and examples.

1 个答案:

答案 0 :(得分:1)

Since jackson-databind 2.5 there is DeserializationFeature for handling this case. It's turned off by default, so you need to configure it in your ObjectMapper:

@Bean
public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);
    return objectMapper;
}

You can see how the custom ObjectMapper for RestTemplate is configured here: How can we configure the internal Jackson mapper when using RestTemplate?

After you're done with the configuration, you can just let Spring wire it for you in your class:

@Autowired
private RestOperations restTemplate;

and use the provided restTemplate instance.