diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java index 6062a86a1..d56807af9 100644 --- a/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -6,10 +6,8 @@ import com.arangodb.entity.ReplicationFactor; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.arangodb.internal.InternalResponse; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.DeserializationContext; @@ -17,7 +15,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.*; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -29,23 +26,10 @@ public final class InternalDeserializers { static final JsonDeserializer RAW_JSON_DESERIALIZER = new JsonDeserializer() { @Override public RawJson deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - // TODO: find a way to access raw bytes directly return RawJson.of(SerdeUtils.INSTANCE.writeJson(p.readValueAsTree())); } }; - static final JsonDeserializer RAW_BYTES_DESERIALIZER = new JsonDeserializer() { - @Override - public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - // TODO: find a way to access raw bytes directly - ByteArrayOutputStream os = new ByteArrayOutputStream(); - try (JsonGenerator g = p.getCodec().getFactory().createGenerator(os)) { - g.writeTree(p.readValueAsTree()); - } - return RawBytes.of(os.toByteArray()); - } - }; - static final JsonDeserializer COLLECTION_STATUS = new JsonDeserializer() { @Override public CollectionStatus deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalModule.java b/core/src/main/java/com/arangodb/internal/serde/InternalModule.java index 3aeae3c24..eefa65759 100644 --- a/core/src/main/java/com/arangodb/internal/serde/InternalModule.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -4,7 +4,6 @@ import com.arangodb.entity.CollectionType; import com.arangodb.entity.InvertedIndexPrimarySort; import com.arangodb.entity.ReplicationFactor; -import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.arangodb.internal.InternalRequest; import com.arangodb.internal.InternalResponse; @@ -22,12 +21,10 @@ enum InternalModule implements Supplier { module = new SimpleModule(); module.addSerializer(RawJson.class, InternalSerializers.RAW_JSON_SERIALIZER); - module.addSerializer(RawBytes.class, InternalSerializers.RAW_BYTES_SERIALIZER); module.addSerializer(InternalRequest.class, InternalSerializers.REQUEST); module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); module.addDeserializer(RawJson.class, InternalDeserializers.RAW_JSON_DESERIALIZER); - module.addDeserializer(RawBytes.class, InternalDeserializers.RAW_BYTES_DESERIALIZER); module.addDeserializer(CollectionStatus.class, InternalDeserializers.COLLECTION_STATUS); module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); module.addDeserializer(ReplicationFactor.class, InternalDeserializers.REPLICATION_FACTOR); diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java index 829563155..c51e50ab6 100644 --- a/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -8,6 +8,7 @@ import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; @@ -16,6 +17,7 @@ import java.io.IOException; import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -104,7 +106,11 @@ public byte[] serializeUserData(Object value) { return serialize(null); } Class clazz = value.getClass(); - if (isManagedClass(clazz)) { + if (RawBytes.class.equals(clazz)) { + return ((RawBytes) value).get(); + } else if (RawJson.class.equals(clazz) && JsonFactory.FORMAT_NAME_JSON.equals(mapper.getFactory().getFormatName())) { + return ((RawJson) value).get().getBytes(StandardCharsets.UTF_8); + } else if (isManagedClass(clazz)) { return serialize(value); } else { return userSerde.serialize(value); @@ -121,8 +127,13 @@ public byte[] serializeCollectionUserData(Iterable value) { } @Override + @SuppressWarnings("unchecked") public T deserializeUserData(byte[] content, Class clazz) { - if (isManagedClass(clazz)) { + if (RawBytes.class.equals(clazz)) { + return (T) RawBytes.of(content); + } else if (RawJson.class.equals(clazz) && JsonFactory.FORMAT_NAME_JSON.equals(mapper.getFactory().getFormatName())) { + return (T) RawJson.of(new String(content, StandardCharsets.UTF_8)); + } else if (isManagedClass(clazz)) { return deserialize(content, clazz); } else { return userSerde.deserialize(content, clazz, RequestContextHolder.INSTANCE.getCtx()); diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java index fa746fedd..31c87ae77 100644 --- a/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -4,11 +4,9 @@ import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; import com.arangodb.internal.ArangoRequestParam; -import com.arangodb.util.RawBytes; import com.arangodb.util.RawJson; import com.arangodb.internal.InternalRequest; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; @@ -26,16 +24,6 @@ public void serialize(RawJson value, JsonGenerator gen, SerializerProvider seria gen.writeTree(SerdeUtils.INSTANCE.parseJson(value.get())); } }; - static final JsonSerializer RAW_BYTES_SERIALIZER = new JsonSerializer() { - @Override - public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - // TODO: find a way to append raw bytes directly - // see https://github.com/FasterXML/jackson-core/issues/914 - try (JsonParser parser = gen.getCodec().getFactory().createParser(value.get())) { - gen.writeTree(parser.readValueAsTree()); - } - } - }; static final JsonSerializer REQUEST = new JsonSerializer() { @Override public void serialize(InternalRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/test-functional/src/test/java/com/arangodb/ArangoDatabaseAsyncTest.java b/test-functional/src/test/java/com/arangodb/ArangoDatabaseAsyncTest.java index e52bb65d7..3bf3cdf7a 100644 --- a/test-functional/src/test/java/com/arangodb/ArangoDatabaseAsyncTest.java +++ b/test-functional/src/test/java/com/arangodb/ArangoDatabaseAsyncTest.java @@ -21,8 +21,8 @@ package com.arangodb; import com.arangodb.entity.*; -import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.*; import com.arangodb.util.MapBuilder; import com.arangodb.util.RawBytes; @@ -668,6 +668,19 @@ void queryWithTTL(ArangoDatabaseAsync db) throws InterruptedException, Execution assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found"); } + @ParameterizedTest + @MethodSource("asyncDbs") + void queryRawBytes(ArangoDatabaseAsync db) throws ExecutionException, InterruptedException { + InternalSerde serde = db.getSerde(); + RawBytes doc = RawBytes.of(serde.serialize(Collections.singletonMap("value", 1))); + RawBytes res = db.query("RETURN @doc", RawBytes.class, Collections.singletonMap("doc", doc)).get() + .getResult().get(0); + JsonNode data = serde.parse(res.get()); + assertThat(data.isObject()).isTrue(); + assertThat(data.get("value").isNumber()).isTrue(); + assertThat(data.get("value").numberValue()).isEqualTo(1); + } + @ParameterizedTest @MethodSource("asyncDbs") void changeQueryCache(ArangoDatabaseAsync db) throws ExecutionException, InterruptedException { diff --git a/test-functional/src/test/java/com/arangodb/ArangoDatabaseTest.java b/test-functional/src/test/java/com/arangodb/ArangoDatabaseTest.java index d041c26ec..2761f8859 100644 --- a/test-functional/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/test-functional/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -22,6 +22,7 @@ import com.arangodb.entity.*; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.*; import com.arangodb.util.*; import com.fasterxml.jackson.databind.JsonNode; @@ -736,6 +737,18 @@ void queryWithTTL(ArangoDatabase db) throws InterruptedException { } } + @ParameterizedTest + @MethodSource("dbs") + void queryRawBytes(ArangoDatabase db) { + InternalSerde serde = db.getSerde(); + RawBytes doc = RawBytes.of(serde.serialize(Collections.singletonMap("value", 1))); + RawBytes res = db.query("RETURN @doc", RawBytes.class, Collections.singletonMap("doc", doc)).next(); + JsonNode data = serde.parse(res.get()); + assertThat(data.isObject()).isTrue(); + assertThat(data.get("value").isNumber()).isTrue(); + assertThat(data.get("value").numberValue()).isEqualTo(1); + } + @ParameterizedTest @MethodSource("dbs") void changeQueryCache(ArangoDatabase db) { diff --git a/test-functional/src/test/java/com/arangodb/serde/SerdeTest.java b/test-functional/src/test/java/com/arangodb/serde/SerdeTest.java index 8a02d6422..fd98e5e37 100644 --- a/test-functional/src/test/java/com/arangodb/serde/SerdeTest.java +++ b/test-functional/src/test/java/com/arangodb/serde/SerdeTest.java @@ -37,8 +37,8 @@ void rawBytesSerde(ContentType type) { InternalSerde s = new InternalSerdeProvider(type).create(); ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); RawBytes raw = RawBytes.of(s.serialize(node)); - byte[] serialized = s.serialize(raw); - RawBytes deserialized = s.deserialize(serialized, RawBytes.class); + byte[] serialized = s.serializeUserData(raw); + RawBytes deserialized = s.deserializeUserData(serialized, RawBytes.class); assertThat(deserialized).isEqualTo(raw); }