2015-05-05 12 views
24

Wiosna 4.1 tworzy instancję Jackson ObjectMapper. Mam powód, aby chcieć @Autowire tej instancji do jednego z moich kontrolerów: kontroler wykonuje kilka drobnych analiz JSON własnych przy użyciu Jackson, ale używa ObjectMapper powinien być jednym i tym samym wystąpieniem, którego używa Spring. Jak mam to osiągnąć?Jak uzyskać obiekt Jackson ObjectMapper w użyciu przez wiosnę 4.1?

Pamiętaj, że nie pytam, jak skonfigurować niestandardowo ObjectMapper w użyciu przez Spring; Jestem zadowolony z domyślnych ustawień. Chcę po prostu łowić instancję używaną przez Spring out, aby ponownie wykorzystać istniejącą instancję w moim własnym kodzie.

+0

Czy na pewno tworzy komponent bean, który może być Autowired, a nie lokalne instancje ObjectMapper? Jeśli tak, czy nie można tego pobrać z komponentu bean obciążenia z kontekstu typu ObjectMapper.class? –

+0

Dodanie właściwości '@ Autowire' typu' ObjectMapper' w kontrolerze nie jest wystarczające. Podobno Spring nie eksponuje go jako standardowego komponentu bean. –

+0

W środowisku testowym otrzymuję go przez dodanie '@ Autowired' na' ObjectMapper' i '@ JsonTest' na klasie testowej – Lu55

Odpowiedz

10

Jeśli spojrzysz na MappingJackson2HttpMessageConverter, zobaczysz, że tworzy on nowy ObjectMapper, ale nie eksponuje go jako komponentu bean. Jest getter, ale jedynym sposobem, w jaki udało mi się go wyłapać w przeszłości, było utworzenie samego siebie, np. 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); 
    } 
} 

Jeśli pracujesz z wiosennym Boot, tam section w podręczniku dedykowane do pracy z ObjectMapper Jeśli utworzysz domyślną Jackson2ObjectMapperBuilder@Bean, powinieneś być w stanie autowire tego samego ObjectMapper instancji w kontrolerze.

+0

Dobrze, spotkałem się z tą ścieżką, ale wiąże się ona z ponownym utworzeniem domyślnych ustawień Jackson, które tworzy Spring. Którego nie chcę robić. –

+0

FWIW, Spring tworzy więcej niż jedną "ObjectMapper". Konwerter wiadomości JSON tworzy taki, jak konwerter XML.Utworzenie trzeciej identycznej z konwerterem wiadomości JSON jest tak proste, jak 'Jackson2ObjectMapperBuilder.json(). Build()'. Ale jeśli naprawdę potrzebujesz, aby była to ta sama instancja, wywołaj tę linię w '@ Bean' i podłącz ją tam, gdzie jej potrzebujesz. Spring zajmie się okablowaniem go w konwerterach. –

+0

Dlaczego sprężyna heck używa różnych instancji OM. To jest takie mylące. Dokumentacja Spring Boot mówi, że spring.jackson.serialization.indent_output = true jest jedyną rzeczą, która wymaga wcześniejszej reakcji na Web. Ale tak naprawdę zmienia tylko komponent bean i nie ma wpływu na konwersję wiadomości. –

25

Jeśli używasz Wiosna Boot z Jacksonem na ścieżce klas i domyślnej implementacji dla JSON parsowania w kontrolerze REST, to powinno działać:

@Autowired 
private ObjectMapper jacksonObjectMapper; 
+13

Nie działa. Przetestowano przy użyciu Spring-boot 1.4.0.M2, który używa sprężyny 4.3.0.RC1 i generuje NoSuchBeanDefinitionException – afaulconbridge

+0

Po pierwsze: działa przy rozruchu sprężynowym 1.5.3 podczas autouzupełniania w komponencie. Po drugie: OSTRZEŻENIE: To jedna z najniebezpieczniejszych idei, jakie miałem do tej pory. Ze względu na jego singletonową naturę, możesz uzyskać bardzo brzydkie problemy używając Spring Objectmapper jako @Autowired bean, np. żaden obiekt w kontrolerach nie jest już serializowany, ponieważ zmieniono parametr seryjny (unwrap_root_value, anyone?) w JAKIEJKOLWIEK klasie, używając automatycznego programu odwzorowującego. Więc proszę: PO PROSTU używaj go, gdy jesteś pewien, że potrzebujesz tylko funkcji ootb programu odwzorowującego. Dla KAŻDEGO innego zastosowania, rozszerz go i stwórz własny niestandardowy mapper. – Dominik

+0

To działa dla mnie –

5

jak zostało powiedziane przez innych, nie można @Autowired bezpośrednio do kontrolera. sugestia

@Emerson FARRUGIA by utworzyć nową instancję za pomocą

Jackson2ObjectMapperBuilder.json().build() 

również nie działa dla mnie, ponieważ nie został uzyskany instancja następujące właściwości konfiguracyjne spring.jackson.*, które potrzebne mu.


Roztwór I stwierdzono, aby uzyskać ObjectMapper od sprężyny MappingJackson2HttpMessageConverter który jest wstrzykiwany.

Więc autowired go:

@Autowired 
private MappingJackson2HttpMessageConverter springMvcJacksonConverter; 

a następnie dostać się ObjectMapper z nim tak:

ObjectMapper objectMapper = springMvcJacksonConverter.getObjectMapper(); 

Ta instancja zachowuje się dokładnie tak, jak własnego nawrócenia wiadomości MVC wiosny jest - to prawdopodobnie jest się tym samym przypadku.

Powiązane problemy