Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ and `org.ehcache:ehcache`
and `com.github.ben-manes.caffeine:jcache`
| Distributed second-level cache support via {infinispan}[Infinispan] | `org.infinispan:infinispan-hibernate-cache-v60`
// | SCRAM authentication support for PostgreSQL | `com.ongres.scram:client:2.1`
| A JSON serialization library for working with JSON datatypes, for example, {jackson}[Jackson] or {yasson}[Yasson] |
`com.fasterxml.jackson.core:jackson-databind` +
| A JSON serialization library for working with JSON datatypes, for example, {jackson}[Jackson 2], {jackson3}[Jackson 3] or {yasson}[Yasson] |
`com.fasterxml.jackson.core:jackson-databind`, `tools.jackson.core:jackson-databind` +
or `org.eclipse:yasson`
| <<spatial,Hibernate Spatial>> | `org.hibernate.orm:hibernate-spatial`
| <<envers,Envers>>, for auditing historical data | `org.hibernate.orm:hibernate-envers`
Expand Down
2 changes: 1 addition & 1 deletion documentation/src/main/asciidoc/introduction/Mapping.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ class Person {
----

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?


[source,groovy]
----
Expand Down
4 changes: 4 additions & 0 deletions hibernate-core/hibernate-core.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ dependencies {
compileOnly jakartaLibs.jsonbApi
compileOnly libs.jackson
compileOnly libs.jacksonXml
compileOnly libs.jackson3
compileOnly libs.jackson3Xml
compileOnly jdbcLibs.postgresql
compileOnly jdbcLibs.edb

Expand Down Expand Up @@ -79,6 +81,8 @@ dependencies {
testImplementation libs.jackson
testRuntimeOnly libs.jacksonXml
testRuntimeOnly libs.jacksonJsr310
testImplementation libs.jackson3
testImplementation libs.jackson3Xml

testAnnotationProcessor project( ':hibernate-processor' )

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,11 @@
import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheMode;
import static org.hibernate.jpa.internal.util.ConfigurationHelper.getFlushMode;
import static org.hibernate.stat.Statistics.DEFAULT_QUERY_STATISTICS_MAX_SIZE;
import static org.hibernate.type.format.jackson.JacksonIntegration.getJsonJackson3FormatMapperOrNull;
import static org.hibernate.type.format.jackson.JacksonIntegration.getJsonJacksonFormatMapperOrNull;
import static org.hibernate.type.format.jackson.JacksonIntegration.getOsonJacksonFormatMapperOrNull;
import static org.hibernate.type.format.jackson.JacksonIntegration.getXMLJackson3FormatMapperOrNull;
import static org.hibernate.type.format.jackson.JacksonIntegration.getXMLJacksonFormatMapperOrNull;
import static org.hibernate.type.format.jackson.JacksonIntegration.isJacksonOsonExtensionAvailable;
import static org.hibernate.type.format.jakartajson.JakartaJsonIntegration.getJakartaJsonBFormatMapperOrNull;

/**
Expand Down Expand Up @@ -851,14 +852,25 @@ private static FormatMapper jsonFormatMapper(Object setting, boolean osonExtensi
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.

if ( jackson3FormatMapper != null ) {
return jackson3FormatMapper;
}

// Prefer the OSON Jackson FormatMapper by default if available
final FormatMapper jsonJacksonFormatMapper =
osonExtensionEnabled && isJacksonOsonExtensionAvailable()
? getOsonJacksonFormatMapperOrNull( creationContext )
: getJsonJacksonFormatMapperOrNull( creationContext );
return jsonJacksonFormatMapper != null
? jsonJacksonFormatMapper
: getJakartaJsonBFormatMapperOrNull();
final FormatMapper jacksonOsonFormatMapper = osonExtensionEnabled
? getOsonJacksonFormatMapperOrNull( creationContext )
: null;
if ( jacksonOsonFormatMapper != null ) {
return jacksonOsonFormatMapper;
}

final FormatMapper jacksonFormatMapper = getJsonJacksonFormatMapperOrNull( creationContext );
if ( jacksonFormatMapper != null ) {
return jacksonFormatMapper;
}

return getJakartaJsonBFormatMapperOrNull();
},
creationContext
);
Expand All @@ -869,10 +881,17 @@ private static FormatMapper xmlFormatMapper(Object setting, StrategySelector sel
setting,
selector,
() -> {
final FormatMapper jacksonFormatMapper = getXMLJacksonFormatMapperOrNull( creationContext );
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.

if (jackson3FormatMapper != null) {
return jackson3FormatMapper;
}

final FormatMapper jacksonFormatMapper = getXMLJacksonFormatMapperOrNull( creationContext );
if (jacksonFormatMapper != null) {
return jacksonFormatMapper;
}

return new JaxbXmlFormatMapper( legacyFormat );
},
creationContext
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.type.format.FormatMapper;
import org.hibernate.type.format.jackson.Jackson3JsonFormatMapper;
import org.hibernate.type.format.jackson.Jackson3XmlFormatMapper;
import org.hibernate.type.format.jackson.JacksonIntegration;
import org.hibernate.type.format.jackson.JacksonJsonFormatMapper;
import org.hibernate.type.format.jackson.JacksonOsonFormatMapper;
Expand Down Expand Up @@ -303,6 +305,11 @@ private static void addJsonFormatMappers(StrategySelectorImpl strategySelector)
JsonBJsonFormatMapper.SHORT_NAME,
JsonBJsonFormatMapper.class
);
strategySelector.registerStrategyImplementor(
FormatMapper.class,
Jackson3JsonFormatMapper.SHORT_NAME,
Jackson3JsonFormatMapper.class
);
strategySelector.registerStrategyImplementor(
FormatMapper.class,
JacksonJsonFormatMapper.SHORT_NAME,
Expand All @@ -318,6 +325,11 @@ private static void addJsonFormatMappers(StrategySelectorImpl strategySelector)
}

private static void addXmlFormatMappers(StrategySelectorImpl strategySelector) {
strategySelector.registerStrategyImplementor(
FormatMapper.class,
Jackson3XmlFormatMapper.SHORT_NAME,
Jackson3XmlFormatMapper.class
);
strategySelector.registerStrategyImplementor(
FormatMapper.class,
JacksonXmlFormatMapper.SHORT_NAME,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.type.format.jackson;

import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.format.AbstractJsonFormatMapper;
import org.hibernate.type.format.FormatMapperCreationContext;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.JacksonModule;
import tools.jackson.databind.cfg.MapperBuilder;
import tools.jackson.databind.json.JsonMapper;

import java.lang.reflect.Type;
import java.util.List;

/**
* @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.)

public final class Jackson3JsonFormatMapper extends AbstractJsonFormatMapper {

public static final String SHORT_NAME = "jackson3";

private final JsonMapper jsonMapper;

public Jackson3JsonFormatMapper() {
this( MapperBuilder.findModules( Jackson3JsonFormatMapper.class.getClassLoader() ) );
}

public Jackson3JsonFormatMapper(FormatMapperCreationContext creationContext) {
this( JacksonIntegration.loadJackson3Modules( creationContext ) );
}

private Jackson3JsonFormatMapper(List<JacksonModule> modules) {
this( JsonMapper.builderWithJackson2Defaults()
.addModules( modules )
.build()
);
}

public Jackson3JsonFormatMapper(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}

@Override
public <T> void writeToTarget(T value, JavaType<T> javaType, Object target, WrapperOptions options)
throws JacksonException {
jsonMapper.writerFor( jsonMapper.constructType( javaType.getJavaType() ) )
.writeValue( (JsonGenerator) target, value );
}

@Override
public <T> T readFromSource(JavaType<T> javaType, Object source, WrapperOptions options) throws JacksonException {
return jsonMapper.readValue( (JsonParser) source, jsonMapper.constructType( javaType.getJavaType() ) );
}

@Override
public boolean supportsSourceType(Class<?> sourceType) {
return JsonParser.class.isAssignableFrom( sourceType );
}

@Override
public boolean supportsTargetType(Class<?> targetType) {
return JsonGenerator.class.isAssignableFrom( targetType );
}

@Override
public <T> T fromString(CharSequence charSequence, Type type) {
try {
return jsonMapper.readValue( charSequence.toString(), jsonMapper.constructType( type ) );
}
catch (JacksonException e) {
throw new IllegalArgumentException( "Could not deserialize string to java type: " + type, e );
}
}

@Override
public <T> String toString(T value, Type type) {
try {
return jsonMapper.writerFor( jsonMapper.constructType( type ) ).writeValueAsString( value );
}
catch (JacksonException e) {
throw new IllegalArgumentException( "Could not serialize object of java type: " + type, e );
}
}
}
Loading