Software Developer
Object mapper is the principal actor elegance of Jackson library. Object mapper magnificence object mapper gives functionality for analyzing and writing JSON, either to and from fundamental POJOs (simple antique java items) or to and from a trendy-cause JSON tree model (JsonNode), as well as related functionality for acting conversions. It is also fairly customizable to paintings both with distinctive sorts of JSON content material and to help more superior item standards inclusive of polymorphism and object identity. Object mapper also acts as a factory for extra superior object reader and object writer lessons.
The easiest way to achieve this goal is to set the hibernate.types.Jackson.object.mapper configuration property in the hibernate.properties file:
hibernate.types.jackson.object.mapper=com.vladmihalcea.hibernate.type.json.loader.CustomObjectMapperSupplier
What’s high-quality about customizing the hibernate-types project is that you may use both the hibernate-precise hibernate.Properties or you could provide a hibernate-types.properties report in case you can not alter hibernate.properties.
You can even supply a different Java properties file via the hibernate-types.properties.path System property.
The CustomObjectMapperSupplier can look as follows:
public class CustomObjectMapperSupplier
implements ObjectMapperSupplier {
@Override
public ObjectMapper get() {
ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
objectMapper.setTimeZone(
TimeZone.getTimeZone("GMT")
);
SimpleModule simpleModule = new SimpleModule(
"SimpleModule",
new Version(1, 0, 0, null, null, null)
);
simpleModule.addSerializer(new MoneySerializer());
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
Here, we are the usage of a custom ObjectMapper that uses our MoneySerializer for managing BigDecimal java item types:
public class MoneySerializer
extends JsonSerializer<BigDecimal> {
@Override
public void serialize(
BigDecimal value,
JsonGenerator jsonGenerator,
SerializerProvider provider)
throws IOException {
jsonGenerator.writeString(
value.setScale(2, BigDecimal.ROUND_HALF_UP).toString()
);
}
@Override
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();
book.setIsbn("978-9730228236");
book.setProperties(
JacksonUtil.toJsonNode(
"{" +
" \"title\": \"High-Performance Java Persistence\"," +
" \"author\": \"Vlad Mihalcea\"," +
" \"publisher\": \"Amazon\"," +
" \"price\": 44.991234567" +
"}"
)
);
entityManager.persist(book);
When fetching the Book entity, we can see that the BigDecimal takes only two decimals:
Book book = entityManager
.unwrap(Session.class)
.bySimpleNaturalId(Book.class)
.load("978-9730228236");
assertEquals(
"44.99",
book.getProperties().get("price").asText()
);
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 JSON PostgreSQL column type:
@Entity(name = "Event")
@Table(name = "event")
public class Event {
@Id
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(),
Location.class
);
properties.put("hibernate.type_contributors",
(TypeContributorList) () -> Collections.singletonList(
(typeContributions, serviceRegistry) ->
typeContributions.contributeType(
jsonType, "location"
)
)
);
The hibernate.type_contributors configuration property allows you to register custom Hibernate Types, and we can use this feature to provide our custom ObjectMapper to the JsonType provided by the hibernate-types project.
So, if we persist the following Event entity:
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);
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());