Come possiamo configurare il mappatore Jackson interno quando si utilizza RestTemplate?

Voglio aggiornare la proprietà SerializationConfig.Feature del mapper di jackson usato da Spring RestTemplate, qualsiasi idea su come posso raggiungerla o dove posso / dovrei configurarla.

Il costruttore predefinito di RestTemplate registra un set di HttpMessageConverter :

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

MappingJacksonHttpMessageConverter a turno, crea direttamente l’istanza di ObjectMapper . Puoi trovare questo convertitore e sostituire ObjectMapper o registrarne uno nuovo prima. Questo dovrebbe funzionare:

 @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 è qualcosa in questo senso:

                 

Si noti che la transizione non è in realtà 1: 1 – Devo creare in modo esplicito l’elenco messageConverters in XML mentre con @Configuration approccio @Configuration potrei fare riferimento a quello esistente e semplicemente modificarlo. Ma questo dovrebbe funzionare.

Se non stai usando Spring IOC, puoi fare qualcosa di simile a questo (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 inizializzerà i suoi convertitori di messaggi predefiniti. È necessario sostituire MappingJackson2HttpMessageConverter con il proprio bean, che dovrebbe utilizzare il programma di mapping degli oggetti che si desidera utilizzare. Questo ha funzionato per me:

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

Per completare le altre risposte: se il tuo ObjectMapper registra solo un Module Jackson con serializzatori / deserializzatori personalizzati, potresti voler registrare il modulo direttamente RestTemplate esistente dal RestTemplate predefinito di MappingJackson2HttpMessageConverter come segue (esempio senza DI ma lo stesso si applica se si utilizza 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); 

Questo ti permetterà di completare la configurazione ObjectMapper originale (come fatto da Spring’s Jackson2ObjectMapperBuilder ), invece di sostituirlo.