2015-05-05 6 views
24

Spring 4.1 создает экземпляр Jackson ObjectMapper. У меня есть причина захотеть, чтобы этот экземпляр был включен в один из моих контроллеров: контроллер выполняет некоторые небольшие JSON-синтаксические разборки самостоятельно, используя Jackson, но используемый ObjectMapper должен быть тем же самым экземпляром, который использует сама Spring. Как я могу это сделать?Как получить Jackson ObjectMapper в использовании Spring 4.1?

Обратите внимание, что я не спрашиваю, как настраивать конфигурацию ObjectMapper, используемую Spring; Я доволен настройками по умолчанию. Я просто хочу ловить экземпляр, используемый Spring, чтобы я мог повторно использовать существующий экземпляр в своем собственном коде.

+0

Вы уверены, что создает компонент, который может быть Autowired, а не локальными экземплярами ObjectMapper? Если да, не может ли это быть извлечено из «компонента загрузки из контекста типа ObjectMapper.class»? –

+0

Недостаточно добавить свойство '@ Autowire' типа' ObjectMapper' в контроллере. Видимо, Spring не раскрывает его как стандартный компонент. –

+0

В тестовой среде я получаю его, добавляя '@ Autowired' в' ObjectMapper' и '@ JsonTest' на тестовый класс – Lu55

ответ

10

Если вы посмотрите на MappingJackson2HttpMessageConverter, вы увидите, что он создает новый ObjectMapper, но не раскрывает его как фасоль. Там есть геттер, но единственный способ, которым я его выудил в прошлом, - это когда я сам создал MappingJackson2HttpMessageConverter, например.

public class WebMvcConfiguration extends WebMvcConfigurerAdapter { 

    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 

     MappingJackson2HttpMessageConverter jacksonMessageConverter = new MappingJackson2HttpMessageConverter(); 
     ObjectMapper objectMapper = jacksonMessageConverter.getObjectMapper(); 

     objectMapper.registerModule(new JodaModule()); 
     objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true); 

     converters.add(jacksonMessageConverter); 
    } 
} 

Если вы работаете с Spring ботинком, есть в ручном предназначил section работать с ObjectMapper Если вы создаете по умолчанию Jackson2ObjectMapperBuilder@Bean, вы должны быть в состоянии autowire того же ObjectMapper экземпляра в контроллере.

+0

Правильно, я столкнулся с этим путем, но он включает в себя повторное создание стандартных настроек Jackson, созданных Spring. Который я не хочу делать. –

+0

FWIW, Spring создает несколько объектов ObjectMapper. Конвертер сообщений JSON создает его, как и XML-конвертер.Создание третьего, идентичного конвертеру сообщений JSON, так же просто, как 'Jackson2ObjectMapperBuilder.json(). Build()'. Но если вам действительно нужно, чтобы это был тот же самый экземпляр, назовите эту строку в '@ Bean' и проведите ее туда, где вам это нужно. Весна позаботится о ее подключении к преобразователям. –

+0

Почему heck spring использует разные экземпляры OM. Это так запутанно. Документация Spring Boot говорит, что spring.jackson.serialization.indent_output = true - это единственное, что вам нужно, чтобы отключить веб-ответ. Но это действительно просто изменяет компонент и не влияет на преобразованное сообщение. –

25

Если вы используете Spring Ботинок с Джексоном на вашем пути к классам и реализации по умолчанию для JSON синтаксического анализа в контроллере REST, то это должно работать:

@Autowired 
private ObjectMapper jacksonObjectMapper; 
+13

Не работает. Протестировано с Spring-boot 1.4.0.M2, которое использует весну 4.3.0.RC1 и выбрасывает NoSuchBeanDefinitionException – afaulconbridge

+0

Сначала: работает с весенней загрузкой 1.5.3 при автоподготовке в компоненте. Второе: ПРЕДУПРЕЖДЕНИЕ: Это одна из самых опасных идей, которые я имел до сих пор. Из-за своей одноэлементности вы можете столкнуться с очень уродливыми проблемами, используя Spring Objectmapper в качестве @Autowired bean-компонента, например. no Объект в ваших контроллерах больше не сериализуется, потому что вы изменили значение serializationfeature (unwrap_root_value, any?) в ЛЮБОЙ класс с помощью автоуверенного картографа. Поэтому, пожалуйста, просто используйте его, когда вы уверены, что вам нужны только функции ootb. Для КАЖДОГО другого usecase, расширьте его и создайте свой собственный картограф – Dominik

+0

Это работает для меня –

5

Как было сказано другими, вы не можете @Autowired это прямо в ваш контроллер. Предложение

@Emerson Фарругия, чтобы создать новый экземпляр с помощью

Jackson2ObjectMapperBuilder.json().build() 

также не работает для меня, потому что полученный экземпляр не следовал свойства spring.jackson.* конфигурации, которые мне нужно это.


Решение, которое я нашел в том, чтобы получить ObjectMapper от MappingJackson2HttpMessageConverter Spring, который является инъекционный.

Так что я autowired его:

@Autowired 
private MappingJackson2HttpMessageConverter springMvcJacksonConverter; 

, а затем получить ObjectMapper от него, как это:

ObjectMapper objectMapper = springMvcJacksonConverter.getObjectMapper(); 

Этот экземпляр ведет себя точно так, как собственное преобразование сообщений Spring MVC - он, вероятно, является в в любом случае.