How do I obtain the Jackson ObjectMapper in use by Spring 4.1?

JavaJsonSpringSpring MvcJackson

Java Problem Overview


Spring 4.1 instantiates a Jackson ObjectMapper instance. I have reason to want to @Autowire that instance into one of my controllers: The controller does some minor JSON parsing of its own using Jackson, but the ObjectMapper it uses should be the one and same instance that Spring itself is using. How do I go about accomplishing that?

Note that I'm not asking how to custom configure the ObjectMapper in use by Spring; I'm happy with the defaults. I just want to fish the instance used by Spring out so that I can re-use the existing instance in my own code.

Java Solutions


Solution 1 - Java

If you're using Spring Boot with Jackson on your classpath and default implementation for JSON parsing in your REST controller, then this should work:

@Autowired
private ObjectMapper jacksonObjectMapper;

Solution 2 - Java

As was said by others, you can't @Autowired it in directly into your controller.

@Emerson Farrugia's suggestion to create a new instance using

Jackson2ObjectMapperBuilder.json().build()

also didn't work for me because the obtained instance was not following the spring.jackson.* configuration properties, which I needed it to.


The solution I found was to obtain the ObjectMapper from Spring's MappingJackson2HttpMessageConverter which is injectable.

So I autowired it:

@Autowired
private MappingJackson2HttpMessageConverter springMvcJacksonConverter;

and then get the ObjectMapper from it like this:

ObjectMapper objectMapper = springMvcJacksonConverter.getObjectMapper();

This instance behaves exactly as Spring MVC's own message conversion - it probably is the same instance anyway.

Solution 3 - Java

If you take a look at MappingJackson2HttpMessageConverter, you'll see that it creates a new ObjectMapper, but doesn't expose it as a bean. There's a getter, but the only way I've fished it out in the past is when I created the MappingJackson2HttpMessageConverter myself, e.g.

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

If you're working with Spring Boot, there's a section in the manual dedicated to working with the ObjectMapper If you create a default Jackson2ObjectMapperBuilder @Bean, you should be able to autowire that same ObjectMapper instance in your controller.

Solution 4 - Java

The ObjectMapper is created by Jackson2ObjectMapperBuilder, and you can inject the builder using:

@Autowired
private Jackson2ObjectMapperBuilder mapperBuilder;

Then use mapperBuilder.build() to build an ObjectMapper instance, and this instance can use configurations in application.properties. Official doc here.

Solution 5 - Java

I have debugged into source code of Spring Boot and found that only when we launch the whole context Jackson2ObjectMapperBuilder will contain the config we put in application.yml.

This means, if we want to generate an ObjectMapper in a Spring Boot test, with JUnit 5, we have to:

@ExtendWith(SpringExtension.class)
@SpringBootTest
class SomeTest {
    @Autowired
    private Jackson2ObjectMapperBuilder builder;
    ...

    @Test
    void testObjectMapper() {
        ObjectMapper mapper = builder.build();


    }

We cannot only make @SpringBootTest(classes = Jackson2ObjectMapperBuilder.class) to generate this builder.

When we bootRun we don't have this problem.

The configuration is set in Jackson2ObjectMapperBuilderCustomizerConfiguration#customize(Jackson2ObjectMapperBuilder builder) method.

enter image description here

Solution 6 - Java

When you try to @Autowire the MappingJackson2HttpMessageConverter it gives you: No qualifying bean of type 'org.springframework.http.converter.json.MappingJackson2HttpMessageConverter' available: expected single matching bean but found 4: mappingJackson2HttpMessageConverter,jacksonHttpMessageConverter,halJacksonHttpMessageConverter,alpsJsonHttpMessageConverter.

This is not a big issue, you can just change your variable name to one of the above to get that instance: @Autowired private MappingJackson2HttpMessageConverter halJacksonHttpMessageConverter;

Solution 7 - Java

A two-stepper if you will;

  1. At your @SpringBootApplication class, add:

    @Bean
    public ObjectMapper mapper() {
      return new ObjectMapper();
    }
    
  2. Anywhere you wish to use ObjectMapper:

    @Autowired
    ObjectMapper mapper;
    

Peace!

Solution 8 - Java

An Update for Spring 4.3:

  • As of Spring 4.3, classes with a single constructor can omit the @Autowired annotation
  • Consequently, if you add a constructor which takes an ObjectMapper parameter it will be autowired with the Jackson ObjectMapper instance without needing to use the annotation @Autowired

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam MaassView Question on Stackoverflow
Solution 1 - JavaTunoView Answer on Stackoverflow
Solution 2 - JavanetmikeyView Answer on Stackoverflow
Solution 3 - JavaEmerson FarrugiaView Answer on Stackoverflow
Solution 4 - JavaLym ZoyView Answer on Stackoverflow
Solution 5 - JavaWesternGunView Answer on Stackoverflow
Solution 6 - JavaAngelVelView Answer on Stackoverflow
Solution 7 - JavaSharan ArumugamView Answer on Stackoverflow
Solution 8 - JavaboardtcView Answer on Stackoverflow