Как мы можем настроить внутренний картограф Jackson при использовании RestTemplate?
Я хочу обновить свойства SerializationConfig.Feature …, которые использует Spring Editor, использующий Spring Restart, любой идеи, как я могу добраться до него или где я могу / должен его настроить.
- Где следует «@Transactional» размещать Сервисный уровень или DAO
- JsonMappingException: не найдено подходящего конструктора для типа : невозможно создать экземпляр из объекта JSON
- Как получить доступ к параметрам задания из ItemReader, в Spring Batch?
- Как управлять исключениями, сброшенными фильтрами весной?
- могу ли я включать информацию пользователя при выдаче токена доступа?
- почему мы не можем авторизовать статические поля весной
- Как создать динамический «в (...)» sql-список через Spring JdbcTemplate?
- Война с весенними ботинками без встроенного tomcat
По умолчанию конструктор RestTemplate
регистрирует набор 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()); }
MappingJacksonHttpMessageConverter
по очереди создает экземпляр MappingJacksonHttpMessageConverter
напрямую. Вы можете найти этот конвертер и заменить ObjectMapper
или зарегистрировать новый перед ним. Это должно работать:
@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 }
В XML это что-то в этом роде:
Обратите внимание, что переход на самом деле не 1: 1 – я должен явно создать список messageConverters
в XML, а при подходе @Configuration
я мог бы ссылаться на существующий и просто изменять его. Но это должно сработать.
Если вы не используете Spring IOC, вы можете сделать что-то вроде этого (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 инициализирует свои преобразователи сообщений по умолчанию. Вы должны заменить MappingJackson2HttpMessageConverter
своим собственным компонентом, который должен использовать объект mapper, который вы хотите использовать. Это сработало для меня:
@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 }
Чтобы выполнить другие ответы: если ваш ObjectMapper
просто регистрирует Module
Jackson с помощью пользовательских сериализаторов / десериализаторов, вы можете захотеть зарегистрировать свой модуль непосредственно на существующей RestTemplate
из RestTemplate
умолчанию для MappingJackson2HttpMessageConverter
следующим образом (пример без DI, но то же самое относится, если использовать 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);
Это позволит вам завершить настройку исходного ObjectMapper
(как это сделано Spring Jackson2ObjectMapperBuilder
) вместо замены.