2015-05-05 17 views
24

Spring 4.1 crea un'istanza di Jackson ObjectMapper. Ho motivo di volere l'istanza di @Autowire in uno dei miei controller: Il controller esegue un piccolo JSON analizzando il proprio utilizzando Jackson, ma lo ObjectMapper che utilizza dovrebbe essere la stessa istanza utilizzata da Spring stessa. Come faccio a realizzare questo?Come ottengo Jackson ObjectMapper in uso da Spring 4.1?

Nota che non sto chiedendo come configurare lo ObjectMapper personalizzato in uso da Spring; Sono felice con le impostazioni predefinite. Voglio solo pescare l'istanza usata da Spring out in modo da poter riutilizzare l'istanza esistente nel mio codice.

+0

Sei sicuro che crei un bean che può essere Autowired e non istanze locali di ObjectMapper? Se sì, non può essere recuperato dal 'bean di caricamento da Context of type ObjectMapper.class'? –

+0

L'aggiunta di una proprietà '@ Autowire' di tipo' ObjectMapper' nel controller non è sufficiente. Apparentemente, Spring non lo espone come un fagiolo standard. –

+0

In ambiente di test lo ottengo aggiungendo '@ Autowired' su' ObjectMapper' e '@ JsonTest' sulla classe di test – Lu55

risposta

10

Se dai un'occhiata a MappingJackson2HttpMessageConverter, vedrai che crea un nuovo ObjectMapper, ma non lo espone come bean. C'è un getter, ma l'unico modo in cui l'ho pescato in passato è quando ho creato io stesso il MappingJackson2HttpMessageConverter, ad es.

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

Se si lavora con la Primavera di avvio, c'è un section nel dedicata manuale per lavorare con il ObjectMapper Se si crea un default Jackson2ObjectMapperBuilder@Bean, si dovrebbe essere in grado di autowire quello stesso ObjectMapper esempio nel controller.

+0

A destra, ho incontrato questo percorso ma comporta la ricreazione delle impostazioni predefinite di Jackson create da Spring. Che non voglio dover fare. –

+0

FWIW, Spring crea più di un 'ObjectMapper'. Il convertitore di messaggi JSON ne crea uno, così come il convertitore XML.Creare un terzo identico al convertitore di messaggi JSON è semplice come 'Jackson2ObjectMapperBuilder.json(). Build()'. Ma se hai davvero bisogno che sia la stessa istanza, chiama quella linea in un '@ Bean' e collegalo ovunque ti serva. La primavera si occuperà di collegarlo ai convertitori. –

+0

Perché la molla diamine usa diverse istanze di OM. Questo è così confuso. La documentazione di Spring Boot dice che spring.jackson.serialization.indent_output = true è l'unica cosa di cui hai bisogno per avere una risposta web ottimizzata. Ma in realtà cambia solo il bean e non ha alcun effetto sul messaggio convertito. –

25

Se si utilizza Primavera di avvio con Jackson sul classpath e implementazione predefinita per JSON parsing nel controller REST, allora questo dovrebbe funzionare:

@Autowired 
private ObjectMapper jacksonObjectMapper; 
+13

Non funziona. Testato con Spring-boot 1.4.0.M2 che utilizza la molla 4.3.0.RC1 e getta NoSuchBeanDefinitionException – afaulconbridge

+0

Primo: funziona con l'avvio a molla 1.5.3 durante l'autowiring in un componente. Secondo: ATTENZIONE: questa è una delle idee più pericolose che ho avuto finora. A causa della sua natura di singleton, è possibile ottenere problemi molto brutti usando lo Spring Objectmapper come un bean @Autowired, ad es. nessun oggetto nei tuoi controller è più serializzato, perché hai cambiato una caratteristica di serializzazione (unwrap_root_value, chiunque?) in QUALSIASI classe usando il mappatore autowired. Quindi, per favore: JUST usalo quando sei sicuro di aver solo bisogno delle funzionalità ootb del mapper. Per OGNI altro caso, estendi e crea il tuo mappatore personalizzato – Dominik

+0

Funziona per me –

5

Come è stato detto da altri, non si può @Autowired direttamente nel tuo controller. Il suggerimento di

@Emerson Farrugia per creare una nuova istanza utilizzando

Jackson2ObjectMapperBuilder.json().build() 

, inoltre, non ha funzionato per me, perché l'istanza ottenuto non seguiva le proprietà spring.jackson.* di configurazione, che avevo bisogno di.


La soluzione che ho trovato è stato quello di ottenere l'ObjectMapper da MappingJackson2HttpMessageConverter di primavera, che è iniettabile.

Così ho autowired che:

@Autowired 
private MappingJackson2HttpMessageConverter springMvcJacksonConverter; 

e quindi ottenere l'ObjectMapper da esso in questo modo:

ObjectMapper objectMapper = springMvcJacksonConverter.getObjectMapper(); 

Questa istanza si comporta esattamente come propria conversione il messaggio di Spring MVC - probabilmente è la stessa istanza comunque.

Problemi correlati