'ObjectMapper enable method is deprecated
I'm upgrading the version of my project and I am currently using jackson-databind-2.13.0 .But I noticed that ObjectMapper's enable method is deprecated.
They said to use it like this instead.
@deprecated Since 2.13 use {@code JsonMapper.builder().enable(...)}
But I couldn't use it.
Below is my ObjectMapper instance creation code. how can I change?
@Bean(name = {"objectMapper"})
@Primary
ObjectMapper objectMapper() {
return newObjectMapper();
}
public static ObjectMapper newObjectMapper() {
ObjectMapper objectMapper =
new ObjectMapper()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer());
javaTimeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer());
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
objectMapper
.registerModule(javaTimeModule)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return objectMapper;
}
Solution:
ObjectMapper objectMapper = JsonMapper
.builder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
.serializationInclusion(Include.NON_NULL).build();
Solution 1:[1]
I would suggest to rewrite your code to either
- Remove this bean and use a fully Spring Boot configured
ObjectMapper
(which has the namejacksonObjectMapper
) - Use the
Jackson2ObjectMapperBuilder
to create an instance of theObjectMapper
.
All of these solutions hide the intricate parts of constructing the ObjectMapper
and will also put the burden of constructing it (properly) on the Spring Boot team, instead of you.
Now for option 1 you would need to remove your @Bean
and place the following in your application.properties
.
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=false
spring.jackson.deserialization.ACCEPT_SINGLE_VALUE_AS_ARRAY=true
spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_PROPERTIES=true
spring.jackson.defaultPropertyInclusion=NON_NULL
When Spring (Boot) detects the JavaTime
module on the classpath it will automatically be registered with the ObjectMapper
, so no need to additionally add that (or the serializers for that matter).
These lines of configuration should you give the same configured ObjectMapper
as your explicitly configured one. H
For the second option you can inject the Jackson2ObjectMapperBuilder
into the method by using an argument, configure the things you want on there and call the build
method in the end.
@Bean(name = {"objectMapper"})
@Primary
ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return newObjectMapper(builder);
}
public static ObjectMapper newObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder
.serializationInclusion(NON_NULL)
.failOnEmptyBeans(false)
.failOnUnknownProperties(false)
.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
You still don't need to register the JavaTime
module as that is still being auto-detected for you.
In theory you could combine 1 and 2 but in your case that wouldn't add much, only some code to construct the ObjectMapper
.
@Bean(name = {"objectMapper"})
@Primary
ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return newObjectMapper(builder);
}
public static ObjectMapper newObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder.build();
}
Solution 2:[2]
I had a similar problem while trying to enable Enum case insensitive deserialization through MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS
.
In my case switching to the builder approach was not possible due to ObjectMapper
being previously constructed by an external source. So the only option was to modify ObjectMapper
deserialization config directly.
Searching for alternatives to avoid deprecated API objectMapper.enable(MappedFeature... f)
I found a workaround by...
- Getting the original
DeserializationConfig
from theObjectMapper
instance. - Creating a 'copy' of the original config with
MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS
enabled by callingwith(MapperFeature... features)
on the config's instance. - Replacing the
ObjectMapper
original config with the new one through the setter method.
This also applies to SerializationConfig
and it is a way of modifying configurations on an already constructed ObjectMapper
without using deprecated APIs.
public void customizeMapper(ObjectMapper objectMapper) {
final DeserializationConfig originalConfig = objectMapper.getDeserializationConfig();
final DeserializationConfig newConfig = originalConfig.with(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
objectMapper.setConfig(newConfig);
}
Note: Using Jackson's builder is definitely a better solution. Consider this approach only if using the builder is not possible.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |