springjackson

How can we configure the internal Jackson mapper when using RestTemplate?


I want to update the SerializationConfig.Feature... properties of the jackson mapper used by Spring RestTemplate, Any idea how I can get to it or where I can/should configure it.


Solution

  • The default RestTemplate constructor registers a set of HttpMessageConverters:

    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:

    @Bean
    public RestOperations restOperations() {
        RestTemplate rest = new RestTemplate();
        //this is crucial!
        rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
        return rest;
    }
    
    @Bean
    public MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
        MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
        converter.setObjectMapper(myObjectMapper());
        return converter;
    }
    
    @Bean
    public 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.