You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2017/05/31 20:06:11 UTC

[02/10] tinkerpop git commit: TINKERPOP-1676 More optimizations to GraphSON serializers

TINKERPOP-1676 More optimizations to GraphSON serializers

Added some tests where there were previously gaps.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/049c9797
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/049c9797
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/049c9797

Branch: refs/heads/master
Commit: 049c979720a84ea9744725fda5f8d2b371ab1751
Parents: e5d2d2b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu May 25 13:29:45 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu May 25 14:52:30 2017 -0400

----------------------------------------------------------------------
 .../io/graphson/AbstractObjectDeserializer.java |   5 +-
 .../io/graphson/GraphSONSerializersV2d0.java    |   5 +-
 .../io/graphson/GraphSONTypeDeserializer.java   |   9 +-
 .../io/graphson/JavaTimeSerializersV2d0.java    |   5 +
 .../io/graphson/TraversalSerializersV2d0.java   | 146 +++++++++++++++----
 .../GraphSONMapperEmbeddedTypeTest.java         | 109 ++++++++++++--
 6 files changed, 227 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/049c9797/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
index 9e4e102..5442fa8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
@@ -24,10 +24,13 @@ import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext;
 import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer;
 
 import java.io.IOException;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 /**
  * Base class for creating deserializers which parses JSON to a {@code Map} to more easily reconstruct an object.
+ * Generally speaking greater performance can be attained with deserializer development that directly uses the
+ * {@code JsonParser}.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
@@ -42,7 +45,7 @@ public abstract class AbstractObjectDeserializer<T> extends StdDeserializer<T> {
         jsonParser.nextToken();
 
         // This will automatically parse all typed stuff.
-        final Map<String, Object> mapData = deserializationContext.readValue(jsonParser, Map.class);
+        final Map<String, Object> mapData = deserializationContext.readValue(jsonParser, LinkedHashMap.class);
 
         return createObject(mapData);
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/049c9797/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
index ffde32c..73bedbb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
@@ -56,6 +56,7 @@ import org.apache.tinkerpop.shaded.jackson.databind.node.ArrayNode;
 import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdKeySerializer;
 import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer;
 import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.type.TypeFactory;
 import org.javatuples.Pair;
 
 import java.io.IOException;
@@ -538,6 +539,7 @@ class GraphSONSerializersV2d0 {
     }
 
     static class PathJacksonDeserializer extends StdDeserializer<Path> {
+        private static final JavaType setType = TypeFactory.defaultInstance().constructCollectionType(HashSet.class, String.class);
 
         public PathJacksonDeserializer() {
             super(Path.class);
@@ -547,7 +549,6 @@ class GraphSONSerializersV2d0 {
         public Path deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             final JsonNode n = jsonParser.readValueAsTree();
             final Path p = MutablePath.make();
-            final JavaType setType = deserializationContext.getConfig().getTypeFactory().constructCollectionType(HashSet.class, String.class);
 
             final ArrayNode labels = (ArrayNode) n.get(GraphSONTokens.LABELS);
             final ArrayNode objects = (ArrayNode) n.get(GraphSONTokens.OBJECTS);
@@ -570,6 +571,7 @@ class GraphSONSerializersV2d0 {
     }
 
     static class VertexPropertyJacksonDeserializer extends StdDeserializer<VertexProperty> {
+        private static final JavaType propertiesType = TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, Object.class);
 
         protected VertexPropertyJacksonDeserializer() {
             super(VertexProperty.class);
@@ -578,7 +580,6 @@ class GraphSONSerializersV2d0 {
         @Override
         public VertexProperty deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             final DetachedVertexProperty vp = DetachedUtil.newDetachedVertexProperty();
-            final JavaType propertiesType = deserializationContext.getConfig().getTypeFactory().constructMapType(HashMap.class, String.class, Object.class);
 
             Map<String, Object> properties;
             while (jsonParser.nextToken() != JsonToken.END_OBJECT) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/049c9797/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
index ceddcc2..5822cb7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeDeserializer.java
@@ -32,8 +32,8 @@ import org.apache.tinkerpop.shaded.jackson.databind.type.TypeFactory;
 import org.apache.tinkerpop.shaded.jackson.databind.util.TokenBuffer;
 
 import java.io.IOException;
-import java.util.List;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
 
 /**
  * Contains main logic for the whole JSON to Java deserialization. Handles types embedded with the version 2.0 of GraphSON.
@@ -47,9 +47,8 @@ public class GraphSONTypeDeserializer extends TypeDeserializerBase {
     private final JavaType baseType;
     private final TypeInfo typeInfo;
 
-    private static final JavaType mapJavaType = TypeFactory.defaultInstance().constructType(Map.class);
-    private static final JavaType arrayJavaType = TypeFactory.defaultInstance().constructType(List.class);
-
+    private static final JavaType mapJavaType = TypeFactory.defaultInstance().constructType(LinkedHashMap.class);
+    private static final JavaType arrayJavaType = TypeFactory.defaultInstance().constructType(ArrayList.class);
 
     GraphSONTypeDeserializer(final JavaType baseType, final TypeIdResolver idRes, final String typePropertyName,
                              final TypeInfo typeInfo, final String valuePropertyName){

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/049c9797/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV2d0.java
index 2950a33..9401d51 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV2d0.java
@@ -85,6 +85,11 @@ final class JavaTimeSerializersV2d0 {
         public T deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException {
             return parse(jsonParser.getText());
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
     final static class DurationJacksonSerializer extends AbstractJavaTimeSerializer<Duration> {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/049c9797/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
index 54e5d9a..f399cfa 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
@@ -35,14 +35,19 @@ import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
 import org.apache.tinkerpop.shaded.jackson.core.JsonParser;
 import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
+import org.apache.tinkerpop.shaded.jackson.core.JsonToken;
 import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext;
+import org.apache.tinkerpop.shaded.jackson.databind.JavaType;
+import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
 import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
 import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer;
 import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
 import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer;
 import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.type.TypeFactory;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
@@ -242,29 +247,40 @@ final class TraversalSerializersV2d0 {
     // DESERIALIZERS //
     //////////////////
 
-    final static class BytecodeJacksonDeserializer extends AbstractObjectDeserializer<Bytecode> {
+    final static class BytecodeJacksonDeserializer extends StdDeserializer<Bytecode> {
+        private static final JavaType listJavaType = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, Object.class);
+        private static final JavaType listListJavaType = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, listJavaType);
 
         public BytecodeJacksonDeserializer() {
             super(Bytecode.class);
         }
 
         @Override
-        public Bytecode createObject(final Map<String, Object> data) {
+        public Bytecode deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             final Bytecode bytecode = new Bytecode();
-            if (data.containsKey(GraphSONTokens.SOURCE)) {
-                final List<List<Object>> instructions = (List) data.get(GraphSONTokens.SOURCE);
-                for (final List<Object> instruction : instructions) {
-                    bytecode.addSource((String) instruction.get(0), Arrays.copyOfRange(instruction.toArray(), 1, instruction.size()));
-                }
-            }
-            if (data.containsKey(GraphSONTokens.STEP)) {
-                final List<List<Object>> instructions = (List) data.get(GraphSONTokens.STEP);
-                for (final List<Object> instruction : instructions) {
-                    bytecode.addStep((String) instruction.get(0), Arrays.copyOfRange(instruction.toArray(), 1, instruction.size()));
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.SOURCE)) {
+                    jsonParser.nextToken();
+                    final List<List<Object>> instructions = deserializationContext.readValue(jsonParser, listListJavaType);
+                    for (final List<Object> instruction : instructions) {
+                        bytecode.addSource((String) instruction.get(0), Arrays.copyOfRange(instruction.toArray(), 1, instruction.size()));
+                    }
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.STEP)) {
+                    jsonParser.nextToken();
+                    final List<List<Object>> instructions = deserializationContext.readValue(jsonParser, listListJavaType);
+                    for (final List<Object> instruction : instructions) {
+                        bytecode.addStep((String) instruction.get(0), Arrays.copyOfRange(instruction.toArray(), 1, instruction.size()));
+                    }
                 }
             }
             return bytecode;
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
     final static class EnumJacksonDeserializer<A extends Enum> extends StdDeserializer<A> {
@@ -283,18 +299,34 @@ final class TraversalSerializersV2d0 {
             }
             throw new IOException("Unknown enum type: " + enumClass);
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
-    final static class PJacksonDeserializer extends AbstractObjectDeserializer<P> {
+    final static class PJacksonDeserializer extends StdDeserializer<P> {
 
         public PJacksonDeserializer() {
             super(P.class);
         }
 
         @Override
-        public P createObject(final Map<String, Object> data) {
-            final String predicate = (String) data.get(GraphSONTokens.PREDICATE);
-            final Object value = data.get(GraphSONTokens.VALUE);
+        public P deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            String predicate = null;
+            Object value = null;
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.PREDICATE)) {
+                    jsonParser.nextToken();
+                    predicate = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    value = deserializationContext.readValue(jsonParser, Object.class);
+                }
+            }
+
             if (predicate.equals(GraphSONTokens.AND) || predicate.equals(GraphSONTokens.OR)) {
                 return predicate.equals(GraphSONTokens.AND) ? new AndP((List<P>) value) : new OrP((List<P>) value);
             } else {
@@ -324,20 +356,38 @@ final class TraversalSerializersV2d0 {
                 }
             }
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
-    final static class LambdaJacksonDeserializer extends AbstractObjectDeserializer<Lambda> {
+    final static class LambdaJacksonDeserializer extends StdDeserializer<Lambda> {
 
         public LambdaJacksonDeserializer() {
             super(Lambda.class);
         }
 
         @Override
-        public Lambda createObject(final Map<String, Object> data) {
-            final String script = (String) data.get(GraphSONTokens.SCRIPT);
-            final String language = (String) data.get(GraphSONTokens.LANGUAGE);
-            final int arguments = ((Number) data.getOrDefault(GraphSONTokens.ARGUMENTS, -1)).intValue();
-            //
+        public Lambda deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            String script = null;
+            String language = null;
+            int arguments = -1;
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.SCRIPT)) {
+                    jsonParser.nextToken();
+                    script = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.LANGUAGE)) {
+                    jsonParser.nextToken();
+                    language = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.ARGUMENTS)) {
+                    jsonParser.nextToken();
+                    arguments = jsonParser.getIntValue();
+                }
+            }
+
             if (-1 == arguments || arguments > 2)
                 return new Lambda.UnknownArgLambda(script, language, arguments);
             else if (0 == arguments)
@@ -347,29 +397,69 @@ final class TraversalSerializersV2d0 {
             else
                 return new Lambda.TwoArgLambda<>(script, language);
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
-    final static class BindingJacksonDeserializer extends AbstractObjectDeserializer<Bytecode.Binding> {
+    final static class BindingJacksonDeserializer extends StdDeserializer<Bytecode.Binding> {
 
         public BindingJacksonDeserializer() {
             super(Bytecode.Binding.class);
         }
 
         @Override
-        public Bytecode.Binding createObject(final Map<String, Object> data) {
-            return new Bytecode.Binding<>((String) data.get(GraphSONTokens.KEY), data.get(GraphSONTokens.VALUE));
+        public Bytecode.Binding deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            String k = null;
+            Object v = null;
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.KEY)) {
+                    jsonParser.nextToken();
+                    k = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    v = deserializationContext.readValue(jsonParser, Object.class);
+                }
+            }
+            return new Bytecode.Binding<>(k, v);
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
         }
     }
 
-    static class TraverserJacksonDeserializer extends AbstractObjectDeserializer<Traverser> {
+    static class TraverserJacksonDeserializer extends StdDeserializer<Traverser> {
 
         public TraverserJacksonDeserializer() {
             super(Traverser.class);
         }
 
         @Override
-        public Traverser createObject(final Map<String, Object> data) {
-            return new DefaultRemoteTraverser<>(data.get(GraphSONTokens.VALUE), (Long) data.get(GraphSONTokens.BULK));
+        public Traverser deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            long bulk = 1;
+            Object v = null;
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.BULK)) {
+                    jsonParser.nextToken();
+                    bulk = deserializationContext.readValue(jsonParser, Long.class);
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    v = deserializationContext.readValue(jsonParser, Object.class);
+                }
+            }
+
+            return new DefaultRemoteTraverser<>(v, bulk);
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/049c9797/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
index 94ccb70..9079c8a 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
@@ -18,10 +18,16 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
+import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.junit.rules.TestName;
 
 import java.time.Duration;
 import java.time.Instant;
@@ -38,7 +44,9 @@ import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.util.Arrays;
 
+import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeThat;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -49,89 +57,158 @@ public class GraphSONMapperEmbeddedTypeTest extends AbstractGraphSONTest {
     @Parameterized.Parameters(name = "{0}")
     public static Iterable<Object[]> data() {
         return Arrays.asList(new Object[][]{
-                {GraphSONMapper.build().version(GraphSONVersion.V1_0).embedTypes(true).create().createMapper()},
-                {GraphSONMapper.build().version(GraphSONVersion.V2_0)
+                {"v1", GraphSONMapper.build().version(GraphSONVersion.V1_0).embedTypes(true).create().createMapper()},
+                {"v2", GraphSONMapper.build().version(GraphSONVersion.V2_0)
                         .addCustomModule(GraphSONXModuleV2d0.build().create(false))
                         .typeInfo(TypeInfo.PARTIAL_TYPES).create().createMapper()},
         });
     }
 
-    @Parameterized.Parameter
+    @Parameterized.Parameter(1)
     public ObjectMapper mapper;
 
+
+    @Parameterized.Parameter(0)
+    public String version;
+
+    @Test
+    public void shouldHandleBiFunctionLambda() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Lambda o = (Lambda) Lambda.biFunction("x,y -> 'test'");
+        assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
+    }
+
+    @Test
+    public void shouldHandleComparatorLambda() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Lambda o = (Lambda) Lambda.comparator("x,y -> x <=> y");
+        assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
+    }
+
+    @Test
+    public void shouldHandleConsumerLambda() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Lambda o = (Lambda) Lambda.consumer("x -> x");
+        assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
+    }
+
+    @Test
+    public void shouldHandleFunctionLambda() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Lambda o = (Lambda) Lambda.function("x -> x");
+        assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
+    }
+
     @Test
-    public void shouldHandleDuration()throws Exception  {
+    public void shouldHandlePredicateLambda() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Lambda o = (Lambda) Lambda.predicate("x -> true");
+        assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
+    }
+
+    @Test
+    public void shouldHandleSupplierLambda() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Lambda o = (Lambda) Lambda.supplier("'test'");
+        assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
+    }
+
+    @Test
+    public void shouldHandleBytecodeBinding() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Bytecode.Binding<String> o = new Bytecode.Binding<>("test", "testing");
+        assertEquals(o, serializeDeserialize(mapper, o, Bytecode.Binding.class));
+    }
+
+    @Test
+    public void shouldHandleTraverser() throws Exception {
+        assumeThat(version, startsWith("v2"));
+
+        final Traverser<String> o = new DefaultRemoteTraverser<>("test", 100);
+        assertEquals(o, serializeDeserialize(mapper, o, Traverser.class));
+    }
+
+    @Test
+    public void shouldHandleDuration() throws Exception  {
         final Duration o = Duration.ZERO;
         assertEquals(o, serializeDeserialize(mapper, o, Duration.class));
     }
+
     @Test
-    public void shouldHandleInstant()throws Exception  {
+    public void shouldHandleInstant() throws Exception  {
         final Instant o = Instant.ofEpochMilli(System.currentTimeMillis());
         assertEquals(o, serializeDeserialize(mapper, o, Instant.class));
     }
 
     @Test
-    public void shouldHandleLocalDate()throws Exception  {
+    public void shouldHandleLocalDate() throws Exception  {
         final LocalDate o = LocalDate.now();
         assertEquals(o, serializeDeserialize(mapper, o, LocalDate.class));
     }
 
     @Test
-    public void shouldHandleLocalDateTime()throws Exception  {
+    public void shouldHandleLocalDateTime() throws Exception  {
         final LocalDateTime o = LocalDateTime.now();
         assertEquals(o, serializeDeserialize(mapper, o, LocalDateTime.class));
     }
 
     @Test
-    public void shouldHandleLocalTime()throws Exception  {
+    public void shouldHandleLocalTime() throws Exception  {
         final LocalTime o = LocalTime.now();
         assertEquals(o, serializeDeserialize(mapper, o, LocalTime.class));
     }
 
     @Test
-    public void shouldHandleMonthDay()throws Exception  {
+    public void shouldHandleMonthDay() throws Exception  {
         final MonthDay o = MonthDay.now();
         assertEquals(o, serializeDeserialize(mapper, o, MonthDay.class));
     }
 
     @Test
-    public void shouldHandleOffsetDateTime()throws Exception  {
+    public void shouldHandleOffsetDateTime() throws Exception  {
         final OffsetDateTime o = OffsetDateTime.now();
         assertEquals(o, serializeDeserialize(mapper, o, OffsetDateTime.class));
     }
 
     @Test
-    public void shouldHandleOffsetTime()throws Exception  {
+    public void shouldHandleOffsetTime() throws Exception  {
         final OffsetTime o = OffsetTime.now();
         assertEquals(o, serializeDeserialize(mapper, o, OffsetTime.class));
     }
 
     @Test
-    public void shouldHandlePeriod()throws Exception  {
+    public void shouldHandlePeriod() throws Exception  {
         final Period o = Period.ofDays(3);
         assertEquals(o, serializeDeserialize(mapper, o, Period.class));
     }
 
     @Test
-    public void shouldHandleYear()throws Exception  {
+    public void shouldHandleYear() throws Exception  {
         final Year o = Year.now();
         assertEquals(o, serializeDeserialize(mapper, o, Year.class));
     }
 
     @Test
-    public void shouldHandleYearMonth()throws Exception  {
+    public void shouldHandleYearMonth() throws Exception  {
         final YearMonth o = YearMonth.now();
         assertEquals(o, serializeDeserialize(mapper, o, YearMonth.class));
     }
 
     @Test
-    public void shouldHandleZonedDateTime()throws Exception  {
+    public void shouldHandleZonedDateTime() throws Exception  {
         final ZonedDateTime o = ZonedDateTime.now();
         assertEquals(o, serializeDeserialize(mapper, o, ZonedDateTime.class));
     }
 
     @Test
-    public void shouldHandleZonedOffset()throws Exception  {
+    public void shouldHandleZonedOffset() throws Exception  {
         final ZoneOffset o  = ZonedDateTime.now().getOffset();
         assertEquals(o, serializeDeserialize(mapper, o, ZoneOffset.class));
     }