micronaut-projects / micronaut-projects/micronaut-data
Add ability to automatically use Micronaut's `JsonMapper` abstraction for Hibernate's FormatMapper for JSON
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 482
- Forks
- 229
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 32
Description
### Feature description
We should be able to allow Hibernate to use the managed JSON mapper from Hibernate, by default it autodetects either Jackson or JSON-B and instantiates it. In the case of Jackson it calls `findModules` which results in a classpath scan that sucks for performance.
Here is some code that does it (needs tests and cleanup):
```java
package hibernate.test;
import io.micronaut.configuration.hibernate.jpa.JpaConfiguration;
import io.micronaut.context.event.BeanCreatedEvent;
import io.micronaut.context.event.BeanCreatedEventListener;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.type.Argument;
import io.micronaut.json.JsonMapper;
import jakarta.inject.Singleton;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.format.FormatMapper;
@Singleton
public class JpaJsonConfigurer implements BeanCreatedEventListener {
private final JsonMapper jsonMapper;
public JpaJsonConfigurer(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
@Override
public JpaConfiguration onCreated(@NonNull BeanCreatedEvent event) {
JpaConfiguration configuration = event.getBean();
Map properties = configuration.getProperties();
if (properties == null) {
properties = new LinkedHashMap<>();
}
configuration.setProperties(properties);
properties.put(AvailableSettings.JSON_FORMAT_MAPPER, new FormatMapper() {
@Override
public T fromString(CharSequence charSequence, JavaType javaType, WrapperOptions wrapperOptions) {
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
return (T) charSequence.toString();
}
try {
return (T) jsonMapper.readValue( charSequence.toString(), Argument.of(javaType.getJavaType()));
}
catch (IOException e) {
throw new IllegalArgumentException( "Could not deserialize string to java type: " + javaType, e );
}
}
@Override
public String toString(T value, JavaType javaType, WrapperOptions wrapperOptions) {
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
return (String) value;
}
try {
return jsonMapper.writeValueAsString((Argument) Argument.of(javaType.getJavaType()), value);
}
catch (IOException e) {
throw new IllegalArgumentException( "Could not serialize object of java type: " + javaType, e );
}
}
});
return configuration;
}
}
```
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review the supplied JpaJsonConfigurer example alongside JpaConfiguration, BeanCreatedEventListener, JsonMapper, and Hibernate's FormatMapper. Add focused tests for serialization, deserialization, and configuration wiring; done means the managed mapper is used without Hibernate's default mapper autodetection.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- database
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100