Serialization
The Java driver uses Jackson internally for serialization and deserialization but you can use a custom implementation for user data
The driver functionalities related to serialization and deserialization (serde) are implemented by 2 different components:
internal serde
user-data serde
The internal serde is based on Jackson
API and is responsible for serializing/deserializing data definition classes
(in packages com.arangodb.model
and com.arangodb.entity
).
This includes all the classes that are not user-data, such as metadata properties
for databases, collections, graphs, etc.
Furthermore, it is used to serialize and deserialize user-data of the following managed types:
com.fasterxml.jackson.databind.JsonNode
and its subclasses (ArrayNode
,ObjectNode
, …)com.arangodb.util.RawJson
com.arangodb.util.RawBytes
com.arangodb.entity.BaseDocument
com.arangodb.entity.BaseEdgeDocument
Note that in arangodb-java-driver-shaded
, due to dependencies relocation, the
fully-qualified class name of first entry above (JsonNode
) is:
com.arangodb.shaded.fasterxml.jackson.databind.JsonNode
.
The same relocation rule is also applied to its subclasses (ArrayNode
, ObjectNode
, …).
The user-data serde is used to serialize and deserialize the user-data, namely the data representing:
- documents
- vertexes
- edges
- AQL bind variables
- transactions parameters
- bodies of custom requests and custom responses (
com.arangodb.Request<T>
andcom.arangodb.Response<T>
).
A user-data serde
implements the com.arangodb.serde.ArangoSerde
interface,
which is an abstract API with no dependencies on specific libraries.
The user-data serde
can be explicitly registered via ArangoDB.Builder#serde(ArangoSerde)
.
If no serde is registered, then the driver will use SPI (Service Provider Interface) to automatically
discover and load serde service providers (instances of com.arangodb.serde.ArangoSerdeProvider
).
In case no user-data serde
is explicitly registered and no serde service provider can be discovered via SPI, then the
internal serde will be used to serialize and deserialize user-data. In this case, please note that the
internal serde is not part of the public API and could change in future releases without notice, thus breaking
client applications relying on it to serialize or deserialize user-data.
Examples of custom user-data serde
implementations can be found here:
- JSON_B serde :
a custom serde implementation based on
JSON-B
(supportingJSON
format only) - Micronaut Serialization serde : a custom serde implementation based on Micronaut Serialization
JacksonSerde (default user-data serde)
The default user-data serde
is com.arangodb.serde.jackson.JacksonSerde
.
It is implemented delegating Jackson
ObjectMapper
, thus compatible with Jackson Streaming, Data Binding and Tree Model API.
It supports both JSON
and VPACK
data formats, while offering the same API to the user.
The JSON
implementation is provided by the module com.arangodb:jackson-serde-json
and transitively imported by arangodb-java-driver
. This implementation will be
used by default.
The VPACK
implementation is provided by the optional module com.arangodb:jackson-serde-vpack
.
Mapping API
JacksonSerde
is fully compatible with Jackson Databind
API. To customize the serialization and deserialization behavior using the
Jackson Data Binding API, entities can be annotated with
Jackson Annotations .
For more advanced customizations refer to Custom serializer section.
Document Annotations
The annotations from package com.arangodb.serde.jackson
can be used to annotate
fields, parameters, getters and setters for mapping values representing ArangoDB
documents metadata (_id
, _key
, _rev
, _from
, _to
):
@Id
@Key
@Rev
@From
@To
Renaming Properties
To use a different serialized name for a field, use the annotation @JsonProperty
.
public class MyObject {
@JsonProperty("title")
private String name;
}
Ignoring properties
To ignore fields use the annotation @JsonIgnore
.
public class Value {
@JsonIgnore
public int internalValue;
}
Custom Configuration
Create an instance of JacksonSerde
, configure the underlying ObjectMapper
and register it in the driver:
JacksonSerde serde = JacksonSerde.of(ContentType.JSON);
serde.configure((ObjectMapper mapper) -> {
// ...
});
ArangoDB adb = new ArangoDB.Builder()
.serde(serde)
// ...
.build();
See also Jackson Databind configurable features.
Custom serializers
The serialization and deserialization can be customized using the lower level
Streaming API or the Tree Model API, creating and registering respectively
JsonSerializer<T>
and JsonDeserializer<T>
, as specified by the Jackson API
for CustomSerializers .
static class PersonSerializer extends JsonSerializer<Person> {
@Override
public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// example using the Streaming API
gen.writeStartObject();
gen.writeFieldName("name");
gen.writeString(value.name);
gen.writeEndObject();
}
}
static class PersonDeserializer extends JsonDeserializer<Person> {
@Override
public Person deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
// example using the Tree Model API
Person person = new Person();
JsonNode rootNode = parser.getCodec().readTree(parser);
JsonNode nameNode = rootNode.get("name");
if (nameNode != null && nameNode.isTextual()) {
person.name = nameNode.asText();
}
return person;
}
}
// registering using annotation
@JsonSerialize(using = PersonSerializer.class)
public static class Person {
public String name;
}
// registering programmatically
JacksonSerde serde = JacksonSerde.of(ContentType.JSON);
serde.configure(mapper -> {
SimpleModule module = new SimpleModule("PersonModule");
module.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(module);
});
ArangoDB adb = new ArangoDB.Builder()
.serde(serde)
// ...
.build();
Jackson datatype and language modules
The JacksonSerde
can be configured
with Jackson datatype modules
as well as Jackson JVM Language modules .
Kotlin
Kotlin language module enables support for Kotlin classes and types and can be registered in the following way:
val arangoDB = ArangoDB.Builder()
.serde(JacksonSerde.of(ContentType.JSON).apply {
configure { it.registerModule(KotlinModule()) }
})
.build()
Scala
Scala language module enables support for Scala classes and types and can be registered in the following way:
val serde = JacksonSerde.of(ContentType.JSON)
serde.configure(mapper => mapper.registerModule(DefaultScalaModule))
val arangoDB = new ArangoDB.Builder()
.serde(arangoJack)
.build()
Java 8 types
Support for Java 8 features is offered by jackson-modules-java8 .
Joda types
Support for Joda data types, such as DateTime, is offered by jackson-datatype-joda .
Metadata fields
Metadata fields _id
, _key
, _rev
, _from
, _to
can be mapped using
respectively the annotations (from package com.arangodb.serde.jackson
):
@Id
, @Key
, @Rev
, @From
, @To
.
public class MyObject {
@Key
private String key;
// ...
}