How to customize the Hypersistence Utils JSON Serializer

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!

Introduction

The Hypersistence Utils open-source project allows you to map JSON, ARRAY, and PostgreSQL ENUM types and provides a simple way of adding immutable Hibernate Types.

After adding support for customizing the Jackson ObjectMapper, the next most-wanted issue was to provide a way to customize the JSON serializing mechanism.

In this article, you are going to see how you can customize the JSON serializer used by the JSON Types.

Declarative configuration

The easiest way to achieve this goal is to set the hypersistence.utils.json.serializer configuration property in the hibernate.properties file:

hypersistence.utils.json.serializer=com.vladmihalcea.hibernate.type.json.configuration.CustomJsonSerializerSupplier

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

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

You can even supply a different Java properties file via the hypersistence-utils.properties.path System property,

The CustomJsonSerializerSupplier can look as follows:

public class CustomJsonSerializerSupplier 
    implements JsonSerializerSupplier {

    @Override
    public JsonSerializer get() {
        return new CustomJsonSerializer();
    }
}

Here, for testing sake, we are using a custom CustomJsonSerializer that implements the JsonSerializer interface:

public class CustomJsonSerializer 
    implements JsonSerializer {

    private static boolean called;

    public static boolean isCalled() {
        return called;
    }

    public static void reset() {
        called = false;
    }

    @Override
    public <T> T clone(T value) {
        called = true;
        return JacksonUtil.clone(value);
    }
}

We are going to use the called static variable to check in our unit test if this method is called by Hypersistence Utils.

assertFalse(CustomJsonSerializer.isCalled());

doInJPA(entityManager -> {
    Location location = new Location();
    location.setCountry("Romania");
    location.setCity("Cluj-Napoca");
    location.setReference(
        BigDecimal.valueOf(2.25262562526626D)
    );

    Event event = new Event();
    event.setId(1L);
    event.setLocation(location);
    entityManager.persist(event);
});

assertTrue(CustomJsonSerializer.isCalled());
CustomJsonSerializer.reset();
assertFalse(CustomJsonSerializer.isCalled());

doInJPA(entityManager -> {
    Event event = entityManager.find(Event.class, 1L);
    assertEquals(
        "2.25262562526626", 
        event.getLocation().getReference().toString()
    );
});

assertTrue(CustomJsonSerializer.isCalled());

As you can see, the CustomJsonSerializer is being used, so you can easily customize the way a given JSON object is serialized by Hypersistence Utils.

I'm running an online workshop on the 20-21 and 23-24 of November about High-Performance Java Persistence.

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

Conclusion

Because of the configuration mechanism I introduced for customizing the ObjectMapper, it is very easy to add new configuration options, like this one which allows you to change the way a given JSON object is serialized by Hypersistence Utils.

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.