Skip to main content

JSON Mapping

Jimmer supports JSON properties. In Java/Kotlin entity types, such properties can be declared as any type other than java.lang.Object and kotlin.Any. In the database, the information stored in the corresponding column is JSON.

info
  • JSON properties are simple properties, not association properties.

  • According to the current implementation, the corresponding column type in Postgres should be jsonb, and the corresponding column type in other databases should be string.

Jimmer provides org.babyfish.jimmer.sql.Serialized. There are two ways to use JSON mapping:

  • Global JSON mapping

    If the property type is a custom class rather than an array, collection, or Map, decorate this class with @Serialized. This way, any properties of the this type in all entities will become JSON properties.

  • Property-level JSON mapping

    The current property can be decorated with @Serialized.

Properties of array, collection, or map types must use property-level mapping; however, global mapping is better for custom types.

Global JSON Mapping

First, define a custom class and decorate it with @Serialized:

UserType.java
@Serialized
public class UserType {

...Omit members, can contain any info...
...As long as Json serialization/deserialization is supported...
}

Then UserType can be used to define properties for any entity:

Book.java
@Entity
public interface Book {

UserType userData();

...Omit other types...
}

Property-level JSON Mapping

Just decorate the property with @Serialized:

Book.java
@Entity
public interface Book {

@Serialized
List<Map<String, SomeType1>> userData1();

@Serialized
Map<String, List<SomeType2>> userData2();

...Omit other types...
}

ObjectMapper Configuration

Use Low-level API

Developers can configure the ObjectMapper for JSON serialization/deserialization of properties decorated with @Serialized.

ObjectMapper mapper1 = ...omitted...;
ObjectMapper mapper2 = ...omitted...;
ObjectMapper mapper3 = ...omitted...;
JSqlClient sqlClient = JSqlClient
.newBuilder()
.setDefaultSerializedTypeObjectMapper(mapper1)
.setSerializedTypeObjectMapper(MetaConfig.class, mapper2)
.setSerializedTypePropMapper(TopicProps.TAGS, mapper3)
...Omit other configurations...
.build();
  • ❶ Set default ObjectMapper to mapper1

    Equivalent to setSerializedTypeObjectMapper(Object.class, mapper1)

  • ❷ For any property whose return type is MetaConfig or its subclass, use mapper2

  • ❸ Explicitly set ObjectMapper for Topic.tags to mapper3

    If the set property is not decorated with @Serialized, an exception will be thrown

Configuration precedence: ❸ > ❷ > ❶

Use Spring Boot Starter

If using the Spring Boot Starter, the SqlClient is created automatically, but users can change the configuration before SqlClient is created via Customizer/KCustomizer:

@Component 
public class SerializationCustomizer implements Customizer {

@Override
public void customize(JSqlClient.Builder builder) {
builder
.setDefaultSerializedTypeObjectMapper(...omitted...)
.setSerializedTypeObjectMapper(MetaConfig.class, ...omitted...)
.setSerializedTypePropMapper(TopicProps.TAGS, ...omitted...);
}
}