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.
-
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:
- Java
- Kotlin
@Serialized
public class UserType {
...Omit members, can contain any info...
...As long as Json serialization/deserialization is supported...
}
@Serialized
data class UserType(
...Omit parameters, can contain any info...
...As long as Json serialization/deserialization is supported...
)
Then UserType can be used to define properties for any entity:
- Java
- Kotlin
@Entity
public interface Book {
UserType userData();
...Omit other types...
}
@Entity
interface Book {
val userData: UserType
...Omit other types...
}
Property-level JSON Mapping
Just decorate the property with @Serialized:
- Java
- Kotlin
@Entity
public interface Book {
@Serialized
List<Map<String, SomeType1>> userData1();
@Serialized
Map<String, List<SomeType2>> userData2();
...Omit other types...
}
@Entity
interface Book {
@Serialized
val userData1: List<Map<String, SomeType1>>
@Serialized
val userData2: Map<String, List<SomeType2>>
...Omit other types...
}
ObjectMapper Configuration
Use Low-level API
Developers can configure the ObjectMapper for JSON serialization/deserialization of properties decorated with @Serialized.
- Java
- Kotlin
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();
val mapper1: ObjectMapper = ...omitted...
val mapper2: ObjectMapper = ...omitted...
val mapper3: ObjectMapper = ...omitted...
val sqlClient = newKSqlClient {
setDefaultSerializedTypeObjectMapper(mapper1) ❶
setSerializedTypeObjectMapper(MetaConfig::class, mapper2) ❷
setSerializedTypePropMapper(Topic::tags, mapper3) ❸
...Omit other configurations...
}
-
❶ Set default ObjectMapper to
mapper1Equivalent to
setSerializedTypeObjectMapper(Object.class, mapper1) -
❷ For any property whose return type is MetaConfig or its subclass, use
mapper2 -
❸ Explicitly set ObjectMapper for
Topic.tagstomapper3If 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:
- Java
- Kotlin
@Component
public class SerializationCustomizer implements Customizer {
@Override
public void customize(JSqlClient.Builder builder) {
builder
.setDefaultSerializedTypeObjectMapper(...omitted...)
.setSerializedTypeObjectMapper(MetaConfig.class, ...omitted...)
.setSerializedTypePropMapper(TopicProps.TAGS, ...omitted...);
}
}
@Component
class SerializationCustomizer : KCustomizer {
override fun customize(dsl: KSqlClientDsl) {
dsl
.setDefaultSerializedTypeObjectMapper(...omitted...)
.setSerializedTypeObjectMapper(MetaConfig::class, ...omitted...)
.setSerializedTypePropMapper(Topic::tags, ...omitted...);
}
}