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
9 changes: 8 additions & 1 deletion documentation/src/main/asciidoc/introduction/Mapping.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -809,13 +809,20 @@ 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:

[source,groovy]
----
runtimeOnly 'com.fasterxml.jackson.core:jackson-databind:{jacksonVersion}'
----

To use Jackson 3 we could add this line to our Gradle build:

[source,groovy]
----
runtimeOnly 'tools.jackson.core:jackson-databind:{jackson3Version}'
----

Now the `name` column of the `Author` table will have the type `jsonb`, and Hibernate will automatically use Jackson to serialize a `Name` to and from JSON format.

[[miscellaneous-mappings]]
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 @@ -852,13 +853,24 @@ private static FormatMapper jsonFormatMapper(Object setting, boolean osonExtensi
selector,
() -> {
// 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;
}

final FormatMapper jackson3FormatMapper = getJsonJackson3FormatMapperOrNull( creationContext );
if ( jackson3FormatMapper != null ) {
return jackson3FormatMapper;
}

return getJakartaJsonBFormatMapperOrNull();
},
creationContext
);
Expand All @@ -870,9 +882,16 @@ private static FormatMapper xmlFormatMapper(Object setting, StrategySelector sel
selector,
() -> {
final FormatMapper jacksonFormatMapper = getXMLJacksonFormatMapperOrNull( creationContext );
return jacksonFormatMapper != null
? jacksonFormatMapper
: new JaxbXmlFormatMapper( legacyFormat );
if (jacksonFormatMapper != null) {
return jacksonFormatMapper;
}

final FormatMapper jackson3FormatMapper = getXMLJackson3FormatMapperOrNull( creationContext );
if (jackson3FormatMapper != null) {
return jackson3FormatMapper;
}

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 @@ -308,6 +310,11 @@
JacksonJsonFormatMapper.SHORT_NAME,
JacksonJsonFormatMapper.class
);
strategySelector.registerStrategyImplementor(
FormatMapper.class,
Jackson3JsonFormatMapper.SHORT_NAME,
Jackson3JsonFormatMapper.class
);
Comment on lines +313 to +317

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
StrategySelectorImpl.registerStrategyImplementor
should be avoided because it has been deprecated.
if ( JacksonIntegration.isJacksonOsonExtensionAvailable() ) {
strategySelector.registerStrategyImplementor(
FormatMapper.class,
Expand All @@ -323,6 +330,11 @@
JacksonXmlFormatMapper.SHORT_NAME,
JacksonXmlFormatMapper.class
);
strategySelector.registerStrategyImplementor(
FormatMapper.class,
Jackson3XmlFormatMapper.SHORT_NAME,
Jackson3XmlFormatMapper.class
);
Comment on lines +333 to +337

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
StrategySelectorImpl.registerStrategyImplementor
should be avoided because it has been deprecated.
strategySelector.registerStrategyImplementor(
FormatMapper.class,
JaxbXmlFormatMapper.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
Loading