Skip to content

Conversation

@nrayburn-tech
Copy link

@nrayburn-tech nrayburn-tech commented Dec 1, 2025

This adds Jackson 3 support alongside the existing Jackson 2 support.

  1. If Jackson 3 is available, it is the preferred option with the automatic detection. This might be undesirable, so it may be worth changing before removing.
  2. OSON doesn't support Jackson 3 right now.
  3. There is duplicate code between the Jackson 2 and Jackson 3 support. There could likely be some refactoring done to reduce this if that's desired (either in this PR or a separate one).
  4. I'm not sure if there are missing tests for this.
  5. I didn't test this in a separate project or anything, just ./gradlew clean build.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.


https://hibernate.atlassian.net/browse/HHH-19890

* @author Christian Beikov
* @author Yanming Zhou
* @author Nick Rayburn
*/
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if the previous author's need to be retained. This file was copied from the existing one that they were on. (I also don't need my name in here either unless it's the project standard, just tried to match what I copied from.)

@cigaly
Copy link
Contributor

cigaly commented Dec 1, 2025

You should take care of backward compatibility. Jackson 3 does not have JSR 310 module since it is handling java.time.* classes, but in a different way than Jackson 2 module.

Here is one example that is showing the problem

JsonJavaTimeMappingTests.java

@nrayburn-tech nrayburn-tech force-pushed the HHH-19890-jackson3-support branch from caa4ff0 to b85e057 Compare December 1, 2025 10:30
@nrayburn-tech
Copy link
Author

Thanks @cigaly, I added the tests and updated the implementation to pass.

Are you suggesting that the new Jackson 3 support should match the existing Jackson 2 support as closely as possible or are you only concerned about the java.time.* handling?

Jackson 3 changed default options for some features, so the new code here would just need to configure those back to the Jackson 2 values. I don't think there's a problem with this, but I wanted to check before I make that change.

@nrayburn-tech nrayburn-tech force-pushed the HHH-19890-jackson3-support branch from b85e057 to f2a08e9 Compare December 1, 2025 10:31
@cigaly
Copy link
Contributor

cigaly commented Dec 1, 2025

Main point is that one should be careful with backward compatibility. If I have project that was using Hibernate + Jackson 2, then I would expect that it will work with Jackson 3 as well without some major code changes. I am not 100% sure how many incompatibilities are introduced when switching from Jackson 2 to 3, java.time is one that I've met while upgrading my project to Spring 7. It is, however, possible that there some other unknown to me.

One good thing with java.time is that Jackson 3 would likely be able to read/deserialize objects written/serialized with Jackson 2. I've run some quick tests where Jackson 2 has been used to serialize and Jackson 3 to deserialize. This is (most likely) working. If Jackson 2 can deserialize what has been serialized with Jackson 3, then my comment about backward compatibility can safely be ignored.

@nrayburn-tech
Copy link
Author

I think it’s a reasonable concern. Even if Jackson can serialize/deserialize the data if it isn’t the same format, there could still be other impact if the data being stored in the database is changed.

  1. This is being added as part of the automatic detection. Maybe it should be opt-in only instead.
  2. I believe this feature is still in Incubating, so compatibility changes like this should be ok but probably need to be well documented. (I got the incubating status from the json_format_mapper, so I could be misinterpreting the incubating status for this feature.)
  3. Jackson changed the defaults for a reason, so configuring back to the Jackson 2 values here feels odd.

Not sure if any of that changes your opinion on how much we configure the Jackson 3 support to align with the existing Jackson 2 support.

I can review the relevant Jackson features, but I think it will be 10+ that need to be explicitly configured to old defaults to be safe.

@nrayburn-tech
Copy link
Author

Jackson offers a method that configures the mapper to use the Jackson 2 settings. I’ll adjust the PR to use that. This will resolve most of the concerns, but it’s probably still worth considering if Jackson 3 is part of the automatic detection or not.

@nrayburn-tech nrayburn-tech force-pushed the HHH-19890-jackson3-support branch from f2a08e9 to fd2673f Compare December 2, 2025 03:37
@nrayburn-tech
Copy link
Author

Updated the code to use the Jackson methods to use the Jackson 2 defaults. I found a few discrepancies and opened PRs against Jackson to resolve those.
FasterXML/jackson-databind#5456
FasterXML/jackson-core#1514


We also need to add Jackson or an implementation of JSONB—for example, Yasson—to our runtime classpath.
To use Jackson we could add this line to our Gradle build:
To use Jackson 2 we could add this line to our Gradle build:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also mention what artifact is needed for Jackson 3?

setting,
selector,
() -> {
final FormatMapper jackson3FormatMapper = getJsonJackson3FormatMapperOrNull( creationContext );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defaulting to Jackson 3 if it's on the classpath might not be such a good idea since people might still want to keep using Jackson 2 for Hibernate ORM if it is also around. I would suggest to use Jackson 3 as fallback if Jackson 2 is not available.

return jacksonFormatMapper != null
? jacksonFormatMapper
: new JaxbXmlFormatMapper( legacyFormat );
final FormatMapper jackson3FormatMapper = getXMLJackson3FormatMapperOrNull( creationContext );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above, I would suggest to use Jackson 3 as fallback if Jackson 2 is not available.

"{\"instant\": 1764576582.000000000, \"duration\": 11640.000000000, \"localDate\": [2025, 12, 1], \"localTime\": [9, 9, 42], \"localDateTime\": [2025, 12, 1, 9, 9, 42]}";
// MySQL
String alternativeMySQLJson =
"\"{\\\"instant\\\": 1764576582.0, \\\"duration\\\": 11640.0, \\\"localDate\\\": [2025, 12, 1], \\\"localTime\\\": [9, 9, 42], \\\"localDateTime\\\": [2025, 12, 1, 9, 9, 42]}\"";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it a bit odd that JsonMappingTests works fine with MySQL without the double backslash quotation but this test requires the backslash quotation. Can you explain the reason for that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants