How to customize the Hypersistence Utils Jackson ObjectMapper

Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn’t that be just awesome?

Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.

So, enjoy spending your time on the things you love rather than fixing performance issues in your production system on a Saturday night!


The Hypersistence Utils open-source project allows you to map JSON, and ARRAY when using JPA and Hibernate.

Since I launched this project, one of the most wanted features was to add support for customizing the underlying Jackson ObjectMapper, and since version 2.1.1, this can be done either declaratively or programmatically.

In this article, you are going to see how to customize the ObjectMapper when using the Hypersistence Utils project.

Declarative configuration

The easiest way to achieve this goal is to set the hypersistence.utils.jackson.object.mapper configuration property in the file:


This property takes the fully-qualified class name of an implementation of the ObjectMapperSupplier interface:

What’s nice about customizing the Hypersistence Utils project is that you can use either the Hibernate-specific or you can provide a file if you cannot alter

You can even supply a different Java properties file via the System property.

The CustomObjectMapperSupplier can look as follows:

public class CustomObjectMapperSupplier 
    implements ObjectMapperSupplier {

    public ObjectMapper get() {
        ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
        SimpleModule simpleModule = new SimpleModule(
            new Version(1, 0, 0, null, null, null)
        simpleModule.addSerializer(new MoneySerializer());
        return objectMapper;

Here, we are using a custom ObjectMapper that uses our own MoneySerializer for handling BigDecimal Java Object types:

public class MoneySerializer 
    extends JsonSerializer<BigDecimal> {

    public void serialize(
                BigDecimal value, 
                JsonGenerator jsonGenerator, 
                SerializerProvider provider)
            throws IOException {
            value.setScale(2, BigDecimal.ROUND_HALF_UP).toString()

    public Class<BigDecimal> handledType() {
        return BigDecimal.class;

So, if you are persisting the following Book entity which has a JSON properties attribute:

Book book = new Book();
           "title": "High-Performance Java Persistence",
           "author": "Vlad Mihalcea",
           "publisher": "Amazon",
           "price": 44.991234567 


When fetching the Book entity, we can see that the BigDecimal takes only two decimals:

Book book = entityManager


Programmatic configuration

For even more flexibility, you can use the programmatic configuration.

Assuming we have the following Object type that we want to serialize as JSON:

public class Location 
    implements Serializable {

    private String country;

    private String city;

    private BigDecimal reference;

    //Getters and setters omitted for brevity

And we have an Event entity that maps the Location Java Object to a jsonb PostgreSQL column type:

@Entity(name = "Event")
@Table(name = "event")
public class Event {

    private Long id;

    @Type(type = "location")
    @Column(columnDefinition = "jsonb")
    private Location location;

    //Getters and setters omitted for brevity

We can use a custom ObjectMapper as follows:

JsonType jsonType = new JsonType(
    new CustomObjectMapperSupplier().get(), 

    (TypeContributorList) () -> Collections.singletonList(
        (typeContributions, serviceRegistry) ->
                jsonType, "location"

The hibernate.type_contributors configuration property allows you to register custom Hibernate Types, and we can use this feature to provide our own custom ObjectMapper to the JsonType provided by the Hypersistence Utils project.

So, if we persist the following Event entity:

Location location = new Location();

Event event = new Event();


When fetching the Event entity, we can see that the BigDecimal takes only two decimals:

Event event = entityManager.find(Event.class, 1L);

assertEquals("2.25", event.getLocation().getReference().toString());

Cool, right?

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.

Seize the deal! 40% discount. Seize the deal! 40% discount.


Not only that you can customize the ObjectMapper when using the Hypersistence Utils project, but the new configuration mechanism will allow for customizing other behaviors as well.

So, stay tuned for more!

Transactions and Concurrency Control eBook

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.