How can I define a custom ObjectMapper bean without overriding the one used by Spring Boot

Since I didn't want to touch Spring's default ObjectMapper, creating a @Primary ObjectMapper to shadow Spring's default ObjectMapper was out of the question.

Instead, what I ended up doing is creating a BeanFactoryPostProcessor which registers in Spring's context a custom, non primary ObjectMapper:

@Component
public class ObjectMapperPostProcessor implements BeanFactoryPostProcessor {

public static final String OBJECT_MAPPER_BEAN_NAME = "persistenceObjectMapper";

@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) {
    final AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
        .genericBeanDefinition(ObjectMapper.class, this::getCustomObjectMapper)
        .getBeanDefinition();
    // Leave Spring's default ObjectMapper (configured by JacksonAutoConfiguration)
    // as primary
    beanDefinition.setPrimary(false);
    final AutowireCandidateQualifier mapperQualifier = new AutowireCandidateQualifier(PersistenceObjectMapper.class);
    beanDefinition.addQualifier(mapperQualifier);
    ((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(OBJECT_MAPPER_BEAN_NAME, beanDefinition);
}

private ObjectMapper getCustomObjectMapper() {
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
    return objectMapper;
}
}

As can be seen in the code above, I also assigned a qualifier to my custom ObjectMapper bean.
My qualifier is an annotation which is annotated with @Qualifier:

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface PersistenceObjectMapper {
}

I can then autowire my custom ObjectMapper using my custom annotation, like this:

@Repository
public class MyDao {
@Autowired
public MyDao(DataSource dataSource, @PersistenceObjectMapper ObjectMapper objectMapper) {
// constructor code
}

The Simone Pontiggia answer is in the correct direction. You should create one @Primary bean, which Spring will use in its internals, and then to create your own ObjectMapper beans and autowired them using @Qualifier.

The problem here is that, creating default bean like:

@Bean
@Primary
public ObjectMapper objectMapper() {
    return new ObjectMapper();
}

Won't actually work as expected, because the Spring default ObjectMapper has additional configurations. The correct way to create default ObjectMapper that will be used by spring, is:

@Bean
@Primary
public ObjectMapper objectMapper() {
    return Jackson2ObjectMapperBuilder.json().build();
}

You can find more information about the Spring default ObjectMapper here: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html under 79.3 Customize the Jackson ObjectMapper


You can provide a standard ObjectMapper and your customized object mapper, and set the standard as @Primary.

Then gives your custom ObjectMapper a name and use it with @Qualifier annotation.

@Configuration
public class Config{

  //This bean will be selected for rest
  @Bean
  @Primary
  public ObjectMapper stdMapper(){
     return new ObjectMapper();
  }

  //You can explicitly refer this bean later
  @Bean("customObjectMapper")
  public ObjectMapper getCustomObjectMapper() {
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
    return objectMapper;
  }
}

Now you can reference your custom mapper

@Repository
@Transactional
public class MyDaoImpl implements MyDao {

@Autowired
@Qualifier("customObjectMapper")
ObjectMapper objectMapper

//Dao implementation...

}

@Resource("custonmObjectMapper") will do the same of @Autowired and @Qualifier together