How can we configure the internal Jackson mapper when using RestTemplate?
The default RestTemplate
constructor registers a set of HttpMessageConverter
s:
this.messageConverters.add(new ByteArrayHttpMessageConverter());this.messageConverters.add(new StringHttpMessageConverter());this.messageConverters.add(new ResourceHttpMessageConverter());this.messageConverters.add(new SourceHttpMessageConverter());this.messageConverters.add(new XmlAwareFormHttpMessageConverter());if (jaxb2Present) { this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());}if (jacksonPresent) { this.messageConverters.add(new MappingJacksonHttpMessageConverter());}if (romePresent) { this.messageConverters.add(new AtomFeedHttpMessageConverter()); this.messageConverters.add(new RssChannelHttpMessageConverter());}
The MappingJacksonHttpMessageConverter
in turns, creates ObjectMapper
instance directly. You can either find this converter and replace ObjectMapper
or register a new one before it. This should work:
@Beanpublic RestOperations restOperations() { RestTemplate rest = new RestTemplate(); //this is crucial! rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter()); return rest;}@Beanpublic MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() { MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter(); converter.setObjectMapper(myObjectMapper()); return converter;}@Beanpublic ObjectMapper myObjectMapper() { //your custom ObjectMapper here}
In XML it is something along these lines:
<bean id="restOperations" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <util:list> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/> <bean class="org.springframework.http.converter.StringHttpMessageConverter"/> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/> <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="objectMapper" ref="customObjectMapper"/> </bean> </util:list> </property></bean><bean id="customObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
Note that the transition isn't really 1:1 - I have to explicitly create messageConverters
list in XML while with @Configuration
approach I could reference existing one and simply modify it. But this should work.
If you are not using Spring IOC, you can do something like this (Java 8):
ObjectMapper objectMapper = new ObjectMapper();// configure your ObjectMapper hereRestTemplate restTemplate = new RestTemplate(); MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();messageConverter.setPrettyPrint(false);messageConverter.setObjectMapper(objectMapper);restTemplate.getMessageConverters().removeIf(m -> m.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));restTemplate.getMessageConverters().add(messageConverter);
RestTemplate will initialize its default message converters. You should replace the MappingJackson2HttpMessageConverter
with your own bean, which should use the object mapper you want to use. This worked for me:
@Beanpublic RestTemplate restTemplate() { final RestTemplate restTemplate = new RestTemplate(); //find and replace Jackson message converter with our own for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) { final HttpMessageConverter<?> httpMessageConverter = restTemplate.getMessageConverters().get(i); if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter){ restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter()); } } return restTemplate;}@Beanpublic MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(myObjectMapper()); return converter;}@Beanpublic ObjectMapper myObjectMapper() { // return your own object mapper}