Guide: @DbJson / @DbJsonB mapping support
July 23, 2026 · View on GitHub
Purpose
Ebean can map @DbJson and @DbJsonB properties in three ways:
- Built-in JSON support, backed by avaje-json-core — no extra dependency.
- Jackson
ObjectMapper, provided byebean-jackson-mapper. - Avaje Jsonb, provided by
ebean-avajejsonb-mapperand its generated adapters.
The built-in mapper handles the common natural JSON types. Add one mapper module for typed collections, POJOs, records, and other custom types.
If a property type is not handled built-in and no mapper module is on the classpath, Ebean fails fast at startup:
Unsupported @DbJson mapping - missing JSON mapper dependency for <property>
Quick reference
| Property type | Built-in (avaje-json-core) | Mapper module |
|---|---|---|
String | ✅ | |
List<String>, List<Long> | ✅ | |
Set<String>, Set<Long> | ✅ | |
Map<String, Object>, Map<String, ?> | ✅ | |
Map<String, String> | ✅ | |
Map<Enum, Object>, Map<Enum, String> | ✅ | |
List/Set of any other element type (Integer, Double, UUID, LocalDate, an enum, a POJO, …) | Jackson or Avaje Jsonb | |
Map with a typed value other than String/Object (Map<String,Integer>, Map<String,UUID>, …) | Jackson or Avaje Jsonb | |
Map with a key other than String or an enum (Map<Integer, …>, Map<UUID, …>) | Jackson or Avaje Jsonb | |
| POJOs, records, or any other type | Jackson or Avaje Jsonb |
Built-in support (no Jackson required)
The built-in path materialises JSON into the natural JSON value types
(String, Long, BigDecimal, Boolean, Map, List). It is therefore type-safe only
for the following declared property types:
-
String— stored as raw JSON text. -
List<String>andList<Long>. -
Set<String>andSet<Long>. -
Map<K, V>where:- the key
KisStringor an enum, and - the value
VisObject,String, or a wildcard?.
So
Map<String,Object>,Map<String,String>,Map<Enum,Object>andMap<Enum,String>are all built-in. - the key
These mappings work across all supported storage types — VARCHAR, CLOB, BLOB, and
Postgres json / jsonb — without ebean-jackson-mapper.
Jackson ObjectMapper
ebean-jackson-mapper uses a Jackson ObjectMapper for the property types not handled
built-in:
- Typed collections —
List/Setwhose element type is notStringorLong(for exampleList<Integer>,List<UUID>,List<LocalDate>,List<MyEnum>,List<MyPojo>). - Typed-value maps — a
Mapvalue type other thanString/Object(for exampleMap<String,Integer>,Map<String,UUID>,Map<String,MyPojo>). - Non-
String/non-enum map keys — for exampleMap<Integer,Object>,Map<UUID,String>. - POJOs, records, and any other custom type.
Jackson marker annotation override: if the field or getter carries a Jackson annotation (anything meta-annotated with
com.fasterxml.jackson.annotation.JacksonAnnotation), Ebean uses theObjectMapperpath even when the type would otherwise be handled built-in.
Adding ebean-jackson-mapper
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>${ebean.version}</version>
</dependency>
A Jackson ObjectMapper must be available (via jackson-databind). Ebean detects it and
registers the mapper-based JSON support automatically.
Avaje Jsonb
ebean-avajejsonb-mapper uses Avaje Jsonb adapters. Annotate each JSON payload type with
@Json, or use @Json.Import, and configure avaje-jsonb-generator as an annotation
processor.
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-avajejsonb-mapper</artifactId>
<version>${ebean.version}</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsonb-generator</artifactId>
<version>${avaje-jsonb.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
For example:
import io.avaje.jsonb.Json;
@Json
public class Address {
public String line1;
public String city;
}
Avaje Jsonb preserves a property's declared generic type, so List<Address> and other
parameterised JSON values use the generated Address adapter.
Avaje JsonNode
@DbJson and @DbJsonB properties declared as io.avaje.json.node.JsonNode are supported
when the application includes avaje-json-node. Its Jsonb component supplies the JSON tree
adapters; no application-generated adapter is needed for the node hierarchy.
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-json-node</artifactId>
<version>${avaje-jsonb.version}</version>
</dependency>
Mapper module selection
Use exactly one mapper module in an application: ebean-jackson-mapper or
ebean-avajejsonb-mapper. Ebean selects a single ScalarJsonMapper service provider, so
having both modules on the runtime classpath is not supported.
The ebean composite dependency includes ebean-jackson-mapper. Applications using Avaje
Jsonb should depend on the individual Ebean modules they need instead of that composite.
To migrate from Jackson to Avaje Jsonb, remove ebean-jackson-mapper, add
ebean-avajejsonb-mapper, and generate adapters for each JSON payload type.
Notes
- Enum map keys are serialised using the enum
name()(for exampleACTIVE), not any@DbEnumValuemapping. Round-trips are correct; the DB value mapping is not applied to JSON keys. @DbArrayalternative: for typed scalar collections (List/SetofInteger,Long,UUID,Double, an enum, …) consider@DbArray, which maps to a native DB array (with a JSON fallback on platforms without array support) and supports more element types than built-in@DbJsoncollections.- The reason typed value/element collections need a real mapper is that the built-in path
only produces natural JSON types — for example a JSON number always parses to
Long.
Choosing
- Prefer the built-in mappings for the common cases (
String, string/long lists and sets, object/string maps) to avoid an additional mapper module. - Add
ebean-jackson-mapperorebean-avajejsonb-mapperwhen you need rich POJO JSON columns or typed collections / typed-value maps.