The Perfect Jackson ObjectMapper
This is the story about my experience working with Java and dealing with Jackson ObjectMapper. While working with pure Java EE, SpringBoot, Quarkus, or any other Java Framework, sooner or later you need to deal with Jackson ObjectMapper.
In this article, I will describe the most common tweaks of Jackson ObjectMapper and how to use it.
Disclaimer. Of course, there is no perfect ObjectMapper configuration. This is just a best practice and base configuration. Depending on your needs, the ObjectMapper configuration can be adjusted.
How to create ObjectMapper instance
First things first, let’s create the ObjectMapper. Please note, that this is an expensive operation. A good practice is to reuse the same instance of ObjectMapper across the entire application.
Classic Singleton
Singletons are great, but using static methods is not a good practice.
Java EE way
If you are using Java Enterprise, you are probably familiar with the @Provider concept. Now you can simple @Inject ObjectMapper instance.
Spring Boot way
SpringBoot is pretty much similar to Java EE, you can use @Configuration and then inject (or @Autowire) ObjectMapper where you need it.
ObjectMapper Customization
We’ve learned how to efficiently create ObjectMapper instances. Now the interesting part, the ObjectMaper customization.
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
Could it happen that your object does not have a specific property or corresponded getter/setter during deserialization? It could happen when you are dealing with some third-party API. Let's secure our service by adding:
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
SerializationFeature.FAIL_ON_EMPTY_BEANS
Could you have empty beans and no-getter? Similar to FAIL_ON_UNKNOWN_PROPERTIES. Let's disable it.
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
JsonInclude.Include.NON_NULL
Do you have large objects and it could contain “null” values? Let's make JSON smaller by excluding properties with “null” values.
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
Oh, dates… Let’s make dates more readable by serializing them in ISO-8601 format.
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Register JavaTimeModule
“Most java.time
types are serialized as numbers (integers or decimals as appropriate) if the SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
feature is enabled. Otherwise, they are serialized in standard ISO-8601 string representation. ISO-8601 specifies formats for representing offset dates and times, zoned dates and times, local dates and times, periods, durations, zones, and more. All java.time
types have a built-in translation to and from ISO-8601 formats.”. Source
mapper.registerModule(new JavaTimeModule());
Summary
The commonly used configuration of ObjectMapper looks like this:
What is your perfect ObjectMapper? Let me know in the comments.
Thank you!
Twitter: @bananandre_
Instagram Art: @andr2art