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.
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.
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);
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
}
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.