This question already has an answer here:
As I understood, Spring is already providing a bean for Jackson ObjectMapper
. Therefore, instead of creating a new bean, I'm trying to customize this bean.
From this blog post, and then this Github project I used Jackson2ObjectMapperBuilder
bean to achieve this customization.
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.findModulesViaServiceLoader(true);
return builder;
}
Then, I was trying to customize the deserializer in order to make it lenient: if an exception is raised when deserializing a property, I want the result object's property to be null
and let the deserialization continue (default is to fail on first property that cannot be deserialized).
I've been able to achieve that with a class NullableFieldsDeserializationProblemHandler
that extends DeserializationProblemHandler
(I do not think the code is relevant but if needed, I can share it).
The simplest way to register this handler is to use the .addHandler()
method of ObjectMapper
. But of course, doing like this, I would need to set that every time I inject and use the ObjectMapper
. I'd like to be able to configure handler so that every time the ObjectMapper
is auto-wired, the handler is already present.
The best solution I came up with so far is to use a @PostConstruct
annotation only to register the problem handler.
@Configuration
public class JacksonConfiguration implements InitializingBean {
@Autowired private ObjectMapper objectMapper;
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.findModulesViaServiceLoader(true);
return builder;
}
@Override
public void afterPropertiesSet() {
objectMapper.addHandler(new NullableFieldsDeserializationProblemHandler());
}
}
But the problem of this solution is that it seems I can still access an autowired ObjectMapper
that doesn't have yet registered the problem handler (I can see it happening after when I need it in debug mode).
Any idea how I should register this handler? I've noticed Jackson2ObjectMapperBuilder
has a .handlerInstantiator()
but I couldn't figure out how to use it.
Note I've also tried with Jackson2ObjectMapperBuilderCustomizer since I'm using Spring Boot but had no better results.
It's not possible to directly add a DeserializationProblemHandler
to the ObjectMapper
via a Jackson2ObjectMapperBuilder
or Jackson2ObjectMapperBuilderCustomizer
. The handlerInstanciator()
method is for something else.
However, it's possible to do so by registering a Jackson module:
- the builder has a
modules()
method - the module has access via
setupModule()
to aSetupContext
instance, which has aaddDeserializationProblemHandler()
method
This works:
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.modules(new MyModule());
}
};
}
private static class MyModule extends SimpleModule {
@Override
public void setupModule(SetupContext context) {
// Required, as documented in the Javadoc of SimpleModule
super.setupModule(context);
context.addDeserializationProblemHandler(new NullableFieldsDeserializationProblemHandler());
}
}
What about writing a bean like this:
@Configuration
public class ObjectMapperConfiguration {
@Bean
ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// jackson 1.9 and before
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// or jackson 2.0
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
}
This is for global configuration. If, instead, what you want to do is to configure the feature for specific a class, use this annotation above the class definition:
@JsonIgnoreProperties(ignoreUnknown = true)
来源:https://stackoverflow.com/questions/48773728/configure-a-jacksons-deserializationproblemhandler-in-spring-environment