After migrating to Spring Boot 3.0.1 and Hibernate 6, I swapped out the Hibernate Types JSON support for the new built in @JdbcTypeCode(SqlTypes.JSON), however my Kotlin data classes failed to deserialize and I had to annotate everything with @JsonCreator and @JsonProperty to fix constructors.
I feel like this should default to the Jackson instance on the Spring context rather than the Jackson library itself, that is pulled in by Hibernate by default. It should be possible to define a custom mapper factory that can be configured via hibernate.type.json_format_mapper and point Hibernate to that instance, see https://github.com/hibernate/hibernate-orm/blob/main/documentation/src/main/asciidoc/userguide/chapters/domain/basic_types.adoc#json-mapping
Comment From: wilkinsona
Thanks for the suggestion. If I have undertood it correctly, you should be able to do this yourself using a HibernatePropertiesCustomizer bean:
@Bean
HibernatePropertiesCustomizer jsonFormatMapperCustomizer(ObjectMapper objectMapper) {
return (properties) -> properties.put(AvailableSettings.JSON_FORMAT_MAPPER,
new JacksonJsonFormatMapper(objectMapper));
}
Can you please try this and let us know if it allows you to remove the @JsonCreator and @JsonProperty annotations?
Comment From: BernhardPosselt
Thank you for getting back, can confirm that this does in fact work fine after removing the annotations. Maybe warrants a separate Kotlin compatibility section in the docs unless it's done by default?
Comment From: wilkinsona
Thanks for confirming that it works for you. We should consider making this the default behaviour so I've labelled this issue as enhancement.
When we come to implement this we should consider the effect that Hibernate using the auto-configured ObjectMapper may have on an application. It could be a breaking change so we may want a way to disable the behavior. We should also try to implement it in such a way that if the user is already customizing the JSON format mapper that we do not overwrite that customization.
Comment From: davidfortin55555
I have implemented the following code but it is nor working with springboot 3.0.1 and hibernate 6
@Bean
HibernatePropertiesCustomizer jsonFormatMapperCustomizer(ObjectMapper objectMapper) {
return (properties) -> properties.put(AvailableSettings.JSON_FORMAT_MAPPER,
new JacksonJsonFormatMapper(objectMapper));
}
Do you habe another proposal?
Comment From: wilkinsona
It should work so, without knowing exactly how it isn't working, it's difficult to propose something else. If you'd like some help, please post a question on Stack Overflow that includes a minimal, reproducible example of the problem.
Comment From: wilkinsona
While looking at #42676 and trying to find some inspiration for a property name, a couple of other things came to mind:
- We should consider auto-configuring a
JsonBJsonFormatMapperwhen there's aJsonbbean. This also raises a question about what to do when there's both anObjectMapperbean and aJsonbbean. We've gotspring.mvc.converters.preferred-json-mapperbut its name clearly indicates that it shouldn't apply outside of Spring MVC's message conversion. - The functionality is marked as
@Incubatingin Hibernate. Are we jumping the gun a bit here and would we be better waiting until its graduated from incubation before we try to offer auto-configuration.
Comment From: philwebb
We discussed this today and we'd like to wait until the Hibernate feature is not @Incubating.
Comment From: OrangeDog
I started looking at Boot 4 today, and it looks like Hibernate 7.1 does not support Jackson 3.
Unlike other dependencies, this did not disqualify it from being supported by Boot, but presumably any user will need to either be stuck on spring-boot-jackson2, or hope that a custom JacksonJsonFormatMapper works without hitting any other incompatibilities in Hibernate.
Comment From: wilkinsona
Unlike other dependencies, this did not disqualify it from being supported by Boot
No other dependency has been disqualified purely because it does not support Jackson 3. Off the top of my head, Flyway and the Elasticsearch Java client both only support Jackson 2 and have not been disqualified.
presumably any user will need to either be stuck on spring-boot-jackson2
Nobody needs to be stuck on spring-boot-jackson2 as it can be used alongside spring-boot-jackson during the ecosystem's transitionary period while Jackson 3 support is not universal.
or hope that a custom JacksonJsonFormatMapper works without hitting any other incompatibilities in Hibernate
I'm not sure what other incompatibilities you're expecting to hit but there should be nothing stopping you from configuring Jackson with a JacksonJsonFormatMapper backed by a Jackson 2 ObjectMapper. That ObjectMapper can be one that you create and configure yourself or, if you add a dependency on spring-boot-jackson2, that is auto-configured by Boot.
Comment From: bclozel
@OrangeDog see https://github.com/spring-projects/spring-boot/issues/47789#issuecomment-3443848646 for support in your app and the relevant issue in Hibernate.