Skip to content

Commit 855dc24

Browse files
committed
new serializer API
1 parent 53d3b23 commit 855dc24

File tree

4 files changed

+233
-0
lines changed

4 files changed

+233
-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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
static JacksonSerde of(final DataType dataType) {
17+
ObjectMapper mapper;
18+
switch (dataType) {
19+
case JSON:
20+
mapper = new ObjectMapper();
21+
break;
22+
case VPACK:
23+
mapper = new VPackMapper();
24+
break;
25+
default:
26+
throw new IllegalStateException("Unexpected value: " + dataType);
27+
}
28+
return of(dataType, mapper);
29+
}
30+
31+
static JacksonSerde of(final DataType dataType, final ObjectMapper mapper) {
32+
return new JacksonSerdeImpl(dataType, mapper);
33+
}
34+
35+
/**
36+
* Deserializes the parsed json node and binds it to the target data type.
37+
*
38+
* @param node parsed json node
39+
* @param clazz class of target data type
40+
* @return deserialized object
41+
*/
42+
default <T> T deserialize(JsonNode node, Class<T> clazz) {
43+
return deserialize(node, (Type) clazz);
44+
}
45+
46+
/**
47+
* Deserializes the parsed json node and binds it to the target data type.
48+
*
49+
* @param node parsed json node
50+
* @param type target data type
51+
* @return deserialized object
52+
*/
53+
<T> T deserialize(JsonNode node, Type type);
54+
55+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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+
import java.nio.charset.StandardCharsets;
11+
12+
final class JacksonSerdeImpl implements JacksonSerde {
13+
14+
private final DataType dataType;
15+
private final ObjectMapper mapper;
16+
private final ObjectMapper jsonMapper = new ObjectMapper();
17+
18+
JacksonSerdeImpl(final DataType dataType, final ObjectMapper mapper) {
19+
this.dataType = dataType;
20+
this.mapper = mapper;
21+
}
22+
23+
/**
24+
* Used for logging and debugging.
25+
*
26+
* @param content byte array
27+
* @return JSON string
28+
*/
29+
public String toJsonString(final byte[] content) {
30+
switch (dataType) {
31+
case JSON:
32+
return new String(content, StandardCharsets.UTF_8);
33+
case VPACK:
34+
try {
35+
JsonNode tree = mapper.readTree(content);
36+
return jsonMapper.writeValueAsString(tree);
37+
} catch (IOException e) {
38+
throw new ArangoDBException(e);
39+
}
40+
default:
41+
throw new IllegalStateException("Unexpected value: " + dataType);
42+
}
43+
}
44+
45+
/**
46+
* Extract the nested content pointed by the json pointer.
47+
* Used for extracting nested user data.
48+
*
49+
* @param content byte array
50+
* @param jsonPointer location of user data
51+
* @return byte array
52+
*/
53+
public byte[] extract(byte[] content, String jsonPointer) {
54+
try {
55+
JsonNode target = mapper.readTree(content).at(jsonPointer);
56+
return mapper.writeValueAsBytes(target);
57+
} catch (IOException e) {
58+
throw new ArangoDBException(e);
59+
}
60+
}
61+
62+
@Override
63+
public DataType getDataType() {
64+
return dataType;
65+
}
66+
67+
@Override
68+
public byte[] serialize(final Object value) {
69+
try {
70+
return mapper.writeValueAsBytes(value);
71+
} catch (JsonProcessingException e) {
72+
throw new ArangoDBException(e);
73+
}
74+
}
75+
76+
@Override
77+
public <T> T deserialize(final byte[] content, final Type type) {
78+
try {
79+
return mapper.readerFor(mapper.constructType(type)).readValue(content);
80+
} catch (IOException e) {
81+
throw new ArangoDBException(e);
82+
}
83+
}
84+
85+
@Override
86+
public <T> T deserialize(final JsonNode node, final Type type) {
87+
try {
88+
return mapper.readerFor(mapper.constructType(type)).readValue(node);
89+
} catch (IOException e) {
90+
throw new ArangoDBException(e);
91+
}
92+
}
93+
94+
}

0 commit comments

Comments
 (0)