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
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
tomapper3
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
:
- 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...);
}
}