Skip to content

Commit 7080d53

Browse files
committed
new serializer API
1 parent 53d3b23 commit 7080d53

File tree

6 files changed

+286
-0
lines changed

6 files changed

+286
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.arangodb.serde;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
5+
import java.lang.reflect.Type;
6+
7+
/**
8+
* Contract for serialization/deserialization of user data.
9+
* Implementations of this interface could be used for customizing serialization/deserialization of user related data
10+
* using serialization/deserialization libraries other than Jackson Databind, like:
11+
* - serialization libraries for specific JVM languages (e.g. Scala, Kotlin, ...)
12+
* - serialization libraries already in use in frameworks (e.g. JSON-B, Micronaut Serialization, ...)
13+
* - high performance serialization libraries (e.g. supporting compile-time databinding code generation)
14+
* - lower level libraries without support to data binding
15+
* <p>
16+
* This interface should not be directly implemented as an adapter to Jackson Databind. A more performant way to provide
17+
* custom implementations based on Jackson Databind is by extending {@link JacksonSerde}, which exposes additional
18+
* methods based on Jackson's types.
19+
* Furthermore, existing implementations {@link JacksonSerde} can be instantiated providing a custom configured Jackson
20+
* ObjectMapper, see {@link JacksonSerde#of(DataType, ObjectMapper)}.
21+
*/
22+
public interface ArangoSerde {
23+
24+
/**
25+
* @return the data type supported by this implementation
26+
*/
27+
DataType getDataType();
28+
29+
/**
30+
* Serializes the object into the target data type. For data type {@link DataType#JSON}, the serialized JSON string
31+
* must be encoded into a byte array using the UTF-8 charset.
32+
*
33+
* @param value object to serialize
34+
* @return serialized byte array
35+
*/
36+
byte[] serialize(Object value);
37+
38+
/**
39+
* Deserializes the content and binds it to the target data type.
40+
* For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset.
41+
*
42+
* @param content byte array to deserialize
43+
* @param clazz class of target data type
44+
* @return deserialized object
45+
*/
46+
default <T> T deserialize(byte[] content, Class<T> clazz) {
47+
return deserialize(content, (Type) clazz);
48+
}
49+
50+
/**
51+
* Deserializes the content and binds it to the target data type.
52+
* For data type {@link DataType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset.
53+
*
54+
* @param content byte array to deserialize
55+
* @param type target data type
56+
* @return deserialized object
57+
*/
58+
<T> T deserialize(byte[] content, Type type);
59+
60+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* DISCLAIMER
3+
*
4+
* Copyright 2016 ArangoDB GmbH, Cologne, Germany
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
*/
20+
package com.arangodb.serde;
21+
22+
public enum DataType {
23+
JSON, VPACK
24+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.arangodb.serde;
2+
3+
import com.arangodb.jackson.dataformat.velocypack.VPackMapper;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
6+
public interface InternalSerde extends JacksonSerde {
7+
8+
/**
9+
* Creates a new InternalSerde with default settings for the specified data type.
10+
*
11+
* @param dataType serialization target data type
12+
* @return the created InternalSerde
13+
*/
14+
static JacksonSerde of(final DataType dataType) {
15+
if (dataType == DataType.JSON) {
16+
return new InternalSerdeImpl(dataType, new ObjectMapper());
17+
} else if (dataType == DataType.VPACK) {
18+
return new InternalSerdeImpl(dataType, new VPackMapper());
19+
} else {
20+
throw new IllegalStateException("Unexpected value: " + dataType);
21+
}
22+
}
23+
24+
/**
25+
* Used for logging and debugging.
26+
*
27+
* @param content byte array
28+
* @return JSON string
29+
*/
30+
String toJsonString(byte[] content);
31+
32+
/**
33+
* Extract the nested content pointed by the json pointer.
34+
* Used for extracting nested user data.
35+
*
36+
* @param content byte array
37+
* @param jsonPointer location of user data
38+
* @return byte array
39+
*/
40+
byte[] extract(byte[] content, String jsonPointer);
41+
42+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.arangodb.serde;
2+
3+
import com.arangodb.ArangoDBException;
4+
import com.fasterxml.jackson.databind.JsonNode;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
7+
import java.io.IOException;
8+
import java.nio.charset.StandardCharsets;
9+
10+
class InternalSerdeImpl extends JacksonSerdeImpl implements InternalSerde {
11+
private final ObjectMapper jsonMapper = new ObjectMapper();
12+
13+
InternalSerdeImpl(DataType dataType, ObjectMapper mapper) {
14+
super(dataType, mapper);
15+
}
16+
17+
@Override
18+
public String toJsonString(final byte[] content) {
19+
switch (dataType) {
20+
case JSON:
21+
return new String(content, StandardCharsets.UTF_8);
22+
case VPACK:
23+
try {
24+
JsonNode tree = mapper.readTree(content);
25+
return jsonMapper.writeValueAsString(tree);
26+
} catch (IOException e) {
27+
throw new ArangoDBException(e);
28+
}
29+
default:
30+
throw new IllegalStateException("Unexpected value: " + dataType);
31+
}
32+
}
33+
34+
@Override
35+
public byte[] extract(final byte[] content, final String jsonPointer) {
36+
try {
37+
JsonNode target = mapper.readTree(content).at(jsonPointer);
38+
return mapper.writeValueAsBytes(target);
39+
} catch (IOException e) {
40+
throw new ArangoDBException(e);
41+
}
42+
}
43+
44+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.arangodb.serde;
2+
3+
import com.arangodb.jackson.dataformat.velocypack.VPackMapper;
4+
import com.fasterxml.jackson.databind.JsonNode;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
7+
import java.lang.reflect.Type;
8+
9+
/**
10+
* Contract for serialization/deserialization of user data, based on Jackson Databind.
11+
* In comparison to {@link ArangoSerde}, this API improves the deserialization performance by allowing reusing the JSON
12+
* tree already parsed by the root deserializer.
13+
*/
14+
public interface JacksonSerde extends ArangoSerde {
15+
16+
/**
17+
* Creates a new JacksonSerde with default settings for the specified data type.
18+
*
19+
* @param dataType serialization target data type
20+
* @return the created JacksonSerde
21+
*/
22+
static JacksonSerde of(final DataType dataType) {
23+
if (dataType == DataType.JSON) {
24+
return of(dataType, new ObjectMapper());
25+
} else if (dataType == DataType.VPACK) {
26+
return of(dataType, new VPackMapper());
27+
} else {
28+
throw new IllegalStateException("Unexpected value: " + dataType);
29+
}
30+
}
31+
32+
/**
33+
* Creates a new JacksonSerde using the provided ObjectMapper.
34+
*
35+
* @param dataType serialization target data type
36+
* @param mapper Jackson ObjectMapper to use
37+
* @return the created JacksonSerde
38+
*/
39+
static JacksonSerde of(final DataType dataType, final ObjectMapper mapper) {
40+
return new JacksonSerdeImpl(dataType, mapper);
41+
}
42+
43+
/**
44+
* Deserializes the parsed json node and binds it to the target data type.
45+
*
46+
* @param node parsed json node
47+
* @param clazz class of target data type
48+
* @return deserialized object
49+
*/
50+
default <T> T deserialize(JsonNode node, Class<T> clazz) {
51+
return deserialize(node, (Type) clazz);
52+
}
53+
54+
/**
55+
* Deserializes the parsed json node and binds it to the target data type.
56+
*
57+
* @param node parsed json node
58+
* @param type target data type
59+
* @return deserialized object
60+
*/
61+
<T> T deserialize(JsonNode node, Type type);
62+
63+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.arangodb.serde;
2+
3+
import com.arangodb.ArangoDBException;
4+
import com.fasterxml.jackson.core.JsonProcessingException;
5+
import com.fasterxml.jackson.databind.JsonNode;
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
8+
import java.io.IOException;
9+
import java.lang.reflect.Type;
10+
11+
class JacksonSerdeImpl implements JacksonSerde {
12+
13+
protected final DataType dataType;
14+
protected final ObjectMapper mapper;
15+
16+
JacksonSerdeImpl(final DataType dataType, final ObjectMapper mapper) {
17+
this.dataType = dataType;
18+
this.mapper = mapper;
19+
}
20+
21+
@Override
22+
public DataType getDataType() {
23+
return dataType;
24+
}
25+
26+
@Override
27+
public byte[] serialize(final Object value) {
28+
try {
29+
return mapper.writeValueAsBytes(value);
30+
} catch (JsonProcessingException e) {
31+
throw new ArangoDBException(e);
32+
}
33+
}
34+
35+
@Override
36+
public <T> T deserialize(final byte[] content, final Type type) {
37+
try {
38+
return mapper.readerFor(mapper.constructType(type)).readValue(content);
39+
} catch (IOException e) {
40+
throw new ArangoDBException(e);
41+
}
42+
}
43+
44+
@Override
45+
public <T> T deserialize(final JsonNode node, final Type type) {
46+
try {
47+
return mapper.readerFor(mapper.constructType(type)).readValue(node);
48+
} catch (IOException e) {
49+
throw new ArangoDBException(e);
50+
}
51+
}
52+
53+
}

0 commit comments

Comments
 (0)