Comment configurer le Jackson mapper interne lors de L'utilisation de RestTemplate?

je veux mettre à jour le SerializationConfig.Caractéristique... propriétés du jackson mapper utilisé par Spring RestTemplate, n'importe quelle idée de comment je peux y accéder ou où je peux/devrais le configurer.

56
demandé sur Usman Ismail 2012-02-21 20:56:00

4 réponses

par défaut RestTemplate constructeur enregistre un ensemble de 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());
}

le MappingJacksonHttpMessageConverter à tour de rôle, crée directement l'instance ObjectMapper . Vous pouvez trouver ce convertisseur et remplacer ObjectMapper ou en enregistrer un nouveau avant elle. Cela devrait fonctionner:

@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
}

En XML c'est quelque chose le long de ces lignes:

<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"/>

notez que la transition n'est pas vraiment 1:1 - je dois créer explicitement la liste messageConverters en XML, alors qu'avec l'approche @Configuration je pourrais faire référence à une liste existante et simplement la modifier. Mais cela devrait fonctionner.

73
répondu Tomasz Nurkiewicz 2012-02-24 21:31:52

si vous n'utilisez pas Spring IOC, vous pouvez faire quelque chose comme ceci (Java 8):

ObjectMapper objectMapper = new ObjectMapper();
// configure your ObjectMapper here

RestTemplate 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);
20
répondu Matt Sidesinger 2016-07-09 21:01:49

RestTemplate initialise ses convertisseurs de messages par défaut. Vous devez remplacer le MappingJackson2HttpMessageConverter par votre propre haricot, qui devrait utiliser le mapper d'objet que vous voulez utiliser. Cela a fonctionné pour moi:

@Bean
public 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;
}

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(myObjectMapper());
    return converter;
}

@Bean
public ObjectMapper myObjectMapper() {
    // return your own object mapper
}
5
répondu mvogiatzis 2018-07-27 10:27:13

pour compléter les autres réponses: si votre ObjectMapper enregistre simplement un Jackson Module avec des sérialiseurs/deserialiseurs personnalisés, vous pouvez enregistrer votre module directement sur le ObjectMapper existant de RestTemplate 's default MappingJackson2HttpMessageConverter comme suit (exemple sans DI mais la même chose s'applique si vous utilisez DI):

    SimpleModule module = new SimpleModule();
    module.addSerializer(...);
    module.addDeserializer(...);

    MappingJackson2HttpMessageConverter messageConverter = restTemplate.getMessageConverters().stream()
                    .filter(MappingJackson2HttpMessageConverter.class::isInstance)
                    .map(MappingJackson2HttpMessageConverter.class::cast)
                    .findFirst().orElseThrow( () -> new RuntimeException("MappingJackson2HttpMessageConverter not found"));
    messageConverter.getObjectMapper().registerModule(module);

cela vous permettra de compléter la configuration de l'original ObjectMapper (comme fait par le ressort Jackson2ObjectMapperBuilder ), à la place de la remplacer.

4
répondu Olivier Gérardin 2017-11-08 10:59:29