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/07/10 21:26:20 UTC

[38/50] [abbrv] tinkerpop git commit: TINKERPOP-1427 Added g:Map for GraphSON 3.0

TINKERPOP-1427 Added g:Map for GraphSON 3.0


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

Branch: refs/heads/TINKERPOP-1427
Commit: bef05a8e958088157b881e6e58937ee8b53a7df3
Parents: 0489cd5
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Sat Jul 1 14:16:57 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jul 10 16:23:52 2017 -0400

----------------------------------------------------------------------
 .../AbstractGraphSONTypeSerializer.java         | 173 +++++++++++
 .../structure/io/graphson/GraphSONMapper.java   |   5 +-
 .../structure/io/graphson/GraphSONModule.java   |  11 +-
 .../structure/io/graphson/GraphSONReader.java   |   9 +-
 .../io/graphson/GraphSONSerializerProvider.java |   1 -
 .../io/graphson/GraphSONSerializersV2d0.java    |   2 +-
 .../io/graphson/GraphSONSerializersV3d0.java    |  28 +-
 .../graphson/GraphSONTypeResolverBuilder.java   |  10 +-
 .../io/graphson/GraphSONTypeSerializer.java     | 245 ---------------
 .../io/graphson/GraphSONTypeSerializerV2d0.java | 112 +++++++
 .../io/graphson/GraphSONTypeSerializerV3d0.java | 139 +++++++++
 .../io/graphson/GraphSONXModuleV2d0.java        |   8 +-
 .../io/graphson/GraphSONXModuleV3d0.java        |   8 +-
 .../io/graphson/JavaTimeSerializersV3d0.java    |   5 +
 .../io/graphson/JavaUtilSerializersV3d0.java    | 109 +++++--
 .../io/graphson/TraversalSerializersV3d0.java   | 146 +++++++--
 .../star/StarGraphGraphSONSerializerV3d0.java   | 165 +++++++++++
 .../GraphSONMapperEmbeddedTypeTest.java         |  39 ++-
 .../GraphSONMapperPartialEmbeddedTypeTest.java  | 297 +++++++++++++++++++
 .../io/graphson/GraphSONMapperTest.java         |   3 +
 ...aphSONMapperV2d0PartialEmbeddedTypeTest.java | 278 -----------------
 .../ser/GraphSONMessageSerializerV3d0Test.java  |  25 +-
 .../jsr223/PythonGraphSONJavaTranslator.java    |   5 +-
 .../server/GremlinDriverIntegrateTest.java      |  34 +++
 .../GremlinServerAuditLogIntegrateTest.java     |   7 +
 .../server/GremlinServerHttpIntegrateTest.java  |   2 +-
 .../server/GremlinServerIntegrateTest.java      |   2 +-
 .../gremlin/structure/io/IoCustomTest.java      |   7 +-
 .../tinkerpop/gremlin/structure/io/IoTest.java  |   4 +-
 .../gremlin/structure/io/util/CustomId.java     |  64 +++-
 .../GraphSONTypedCompatibilityTest.java         |   7 +-
 .../_3_3_0/authenticationchallenge-v3d0.json    |  10 +-
 .../_3_3_0/authenticationresponse-v3d0.json     |   4 +-
 .../io/graphson/_3_3_0/metrics-v3d0.json        |  55 ++--
 .../structure/io/graphson/_3_3_0/path-v3d0.json | 122 +-------
 .../io/graphson/_3_3_0/sessionclose-v3d0.json   |   5 +-
 .../io/graphson/_3_3_0/sessioneval-v3d0.json    |  15 +-
 .../_3_3_0/sessionevalaliased-v3d0.json         |  21 +-
 .../graphson/_3_3_0/sessionlesseval-v3d0.json   |  12 +-
 .../_3_3_0/sessionlessevalaliased-v3d0.json     |  18 +-
 .../io/graphson/_3_3_0/standardresult-v3d0.json |  10 +-
 .../graphson/_3_3_0/traversalmetrics-v3d0.json  | 112 ++++---
 .../structure/io/graphson/_3_3_0/tree-v3d0.json |   8 +-
 .../structure/TinkerIoRegistryV3d0.java         |   3 +-
 44 files changed, 1448 insertions(+), 897 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractGraphSONTypeSerializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractGraphSONTypeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractGraphSONTypeSerializer.java
new file mode 100644
index 0000000..6eb65e1
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractGraphSONTypeSerializer.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.shaded.jackson.annotation.JsonTypeInfo;
+import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
+import org.apache.tinkerpop.shaded.jackson.databind.BeanProperty;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeIdResolver;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Extension of the Jackson's default TypeSerializer. An instance of this object will be passed to the serializers
+ * on which they can safely call the utility methods to serialize types and making it compatible with the version
+ * 2.0+ of GraphSON.
+ *
+ * @author Kevin Gallardo (https://kgdo.me)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class AbstractGraphSONTypeSerializer extends TypeSerializer {
+
+    protected final TypeIdResolver idRes;
+    protected final String propertyName;
+    protected final TypeInfo typeInfo;
+    protected final String valuePropertyName;
+    protected final Map<Class, Class> classMap = new HashMap<>();
+
+    AbstractGraphSONTypeSerializer(final TypeIdResolver idRes, final String propertyName, final TypeInfo typeInfo,
+                                   final String valuePropertyName) {
+        this.idRes = idRes;
+        this.propertyName = propertyName;
+        this.typeInfo = typeInfo;
+        this.valuePropertyName = valuePropertyName;
+    }
+
+
+    @Override
+    public TypeSerializer forProperty(final BeanProperty beanProperty) {
+        return this;
+    }
+
+    @Override
+    public JsonTypeInfo.As getTypeInclusion() {
+        return null;
+    }
+
+    @Override
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    @Override
+    public TypeIdResolver getTypeIdResolver() {
+        return idRes;
+    }
+
+    @Override
+    public void writeTypePrefixForScalar(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        if (canWriteTypeId()) {
+            writeTypePrefix(jsonGenerator, getTypeIdResolver().idFromValueAndType(o, getClassFromObject(o)));
+        }
+    }
+
+    @Override
+    public void writeTypePrefixForObject(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        jsonGenerator.writeStartObject();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(Map);
+    }
+
+    @Override
+    public void writeTypePrefixForArray(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        jsonGenerator.writeStartArray();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(List);
+    }
+
+    @Override
+    public void writeTypeSuffixForScalar(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        if (canWriteTypeId()) {
+            writeTypeSuffix(jsonGenerator);
+        }
+    }
+
+    @Override
+    public void writeTypeSuffixForObject(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        jsonGenerator.writeEndObject();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(Map);
+    }
+
+    @Override
+    public void writeTypeSuffixForArray(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        jsonGenerator.writeEndArray();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(List);
+    }
+
+    @Override
+    public void writeCustomTypePrefixForScalar(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
+        if (canWriteTypeId()) {
+            writeTypePrefix(jsonGenerator, s);
+        }
+    }
+
+    @Override
+    public void writeCustomTypePrefixForObject(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
+        jsonGenerator.writeStartObject();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(s);
+    }
+
+    @Override
+    public void writeCustomTypePrefixForArray(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
+        jsonGenerator.writeStartArray();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(s);
+    }
+
+    @Override
+    public void writeCustomTypeSuffixForScalar(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
+        if (canWriteTypeId()) {
+            writeTypeSuffix(jsonGenerator);
+        }
+    }
+
+    @Override
+    public void writeCustomTypeSuffixForObject(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
+        jsonGenerator.writeEndObject();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(s);
+    }
+
+    @Override
+    public void writeCustomTypeSuffixForArray(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
+        jsonGenerator.writeEndArray();
+        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(s);
+    }
+
+    protected boolean canWriteTypeId() {
+        return typeInfo != null
+                && typeInfo == TypeInfo.PARTIAL_TYPES;
+    }
+
+    protected void writeTypePrefix(final JsonGenerator jsonGenerator, final String s) throws IOException {
+        jsonGenerator.writeStartObject();
+        jsonGenerator.writeStringField(this.getPropertyName(), s);
+        jsonGenerator.writeFieldName(this.valuePropertyName);
+    }
+
+    protected void writeTypeSuffix(final JsonGenerator jsonGenerator) throws IOException {
+        jsonGenerator.writeEndObject();
+    }
+
+    /**
+     * We force only **one** translation of a Java object to a domain specific object. i.e. users register typeIDs
+     * and serializers/deserializers for the predefined types we have in the spec. Graph, Vertex, Edge,
+     * VertexProperty, etc... And **not** their implementations (TinkerGraph, DetachedVertex, TinkerEdge, etc..)
+     */
+    protected abstract Class getClassFromObject(final Object o);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
index 6b6bbf7..eb3c9ad 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
@@ -94,9 +94,12 @@ public class GraphSONMapper implements Mapper<ObjectMapper> {
             om.findAndRegisterModules();
 
         // graphson 3.0 only allows type - there is no option to remove embedded types
+        if (version == GraphSONVersion.V3_0 && typeInfo == TypeInfo.NO_TYPES)
+            throw new IllegalStateException(String.format("GraphSON 3.0 does not support %s", TypeInfo.NO_TYPES));
+
         if (version == GraphSONVersion.V3_0 || (version == GraphSONVersion.V2_0 && typeInfo != TypeInfo.NO_TYPES)) {
             final GraphSONTypeIdResolver graphSONTypeIdResolver = new GraphSONTypeIdResolver();
-            final TypeResolverBuilder typer = new GraphSONTypeResolverBuilder()
+            final TypeResolverBuilder typer = new GraphSONTypeResolverBuilder(version)
                     .typesEmbedding(getTypeInfo())
                     .valuePropertyName(GraphSONTokens.VALUEPROP)
                     .init(JsonTypeInfo.Id.CUSTOM, graphSONTypeIdResolver)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 019112b..22dc6b2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -71,6 +71,7 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.star.DirectionalStarGraph;
 import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphGraphSONSerializerV1d0;
 import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphGraphSONSerializerV2d0;
+import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphGraphSONSerializerV3d0;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
 
 import java.time.Duration;
@@ -122,6 +123,9 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     put(Double.class, "Double");
                     put(Float.class, "Float");
 
+                    put(Map.Entry.class, "Entry");
+                    put(Map.class, "Map");
+
                     // Tinkerpop Graph objects
                     put(Lambda.class, "Lambda");
                     put(Vertex.class, "Vertex");
@@ -196,11 +200,12 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
             addSerializer(TraversalMetrics.class, new GraphSONSerializersV3d0.TraversalMetricsJacksonSerializer());
             addSerializer(TraversalExplanation.class, new GraphSONSerializersV3d0.TraversalExplanationJacksonSerializer());
             addSerializer(Path.class, new GraphSONSerializersV3d0.PathJacksonSerializer());
-            addSerializer(DirectionalStarGraph.class, new StarGraphGraphSONSerializerV2d0(normalize));
+            addSerializer(DirectionalStarGraph.class, new StarGraphGraphSONSerializerV3d0(normalize));
             addSerializer(Tree.class, new GraphSONSerializersV3d0.TreeJacksonSerializer());
 
             // java.util
             addSerializer(Map.Entry.class, new JavaUtilSerializersV3d0.MapEntryJacksonSerializer());
+            addSerializer(Map.class, new JavaUtilSerializersV3d0.MapJacksonSerializer());
 
             // need to explicitly add serializers for those types because Jackson doesn't do it at all.
             addSerializer(Integer.class, new GraphSONSerializersV3d0.IntegerGraphSONSerializer());
@@ -237,6 +242,10 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
             addDeserializer(TraversalMetrics.class, new GraphSONSerializersV3d0.TraversalMetricsJacksonDeserializer());
             addDeserializer(Tree.class, new GraphSONSerializersV3d0.TreeJacksonDeserializer());
 
+            // java.util
+            addDeserializer(Map.Entry.class, new JavaUtilSerializersV3d0.MapEntryJacksonDeserializer());
+            addDeserializer(Map.class, new JavaUtilSerializersV3d0.MapJacksonDeserializer());
+
             // numbers
             addDeserializer(Integer.class, new GraphSONSerializersV3d0.IntegerJackonsDeserializer());
             addDeserializer(Double.class, new GraphSONSerializersV3d0.DoubleJackonsDeserializer());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
index 3f63b96..056d3c8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
@@ -52,6 +52,7 @@ import java.io.OutputStream;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Function;
@@ -73,8 +74,8 @@ public final class GraphSONReader implements GraphReader {
     private final GraphSONVersion version;
     private boolean unwrapAdjacencyList = false;
 
-    final TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {
-    };
+    final TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {};
+    final TypeReference<LinkedHashMap<String, Object>> linkedHashMapTypeReference = new TypeReference<LinkedHashMap<String, Object>>() {};
 
     private GraphSONReader(final Builder builder) {
         mapper = builder.mapper.createMapper();
@@ -173,7 +174,9 @@ public final class GraphSONReader implements GraphReader {
                              final Function<Attachable<Vertex>, Vertex> vertexAttachMethod,
                              final Function<Attachable<Edge>, Edge> edgeAttachMethod,
                              final Direction attachEdgesOfThisDirection) throws IOException {
-        final Map<String, Object> vertexData = mapper.readValue(inputStream, mapTypeReference);
+        // graphson v3 has special handling for generic Map instances, by forcing to linkedhashmap (which is probably
+        // what it should have been anyway) stargraph format can remain unchanged across all versions
+        final Map<String, Object> vertexData = mapper.readValue(inputStream, version == GraphSONVersion.V3_0 ? linkedHashMapTypeReference : mapTypeReference);
         final StarGraph starGraph = StarGraphGraphSONDeserializer.readStarGraphVertex(vertexData);
         if (vertexAttachMethod != null) vertexAttachMethod.apply(starGraph.getStarVertex());
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
index bd7f966..7744b79 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
@@ -44,7 +44,6 @@ final class GraphSONSerializerProvider extends DefaultSerializerProvider {
             setDefaultKeySerializer(new GraphSONSerializersV2d0.GraphSONKeySerializer());
             unknownTypeSerializer = new ToStringGraphSONSerializer();
         } else {
-            setDefaultKeySerializer(new GraphSONSerializersV3d0.GraphSONKeySerializer());
             unknownTypeSerializer = new ToStringGraphSONSerializer();
         }
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/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 095bfe6..717dcfa 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
@@ -703,4 +703,4 @@ class GraphSONSerializersV2d0 {
             return true;
         }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java
index 6f6e011..5fe8e74 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java
@@ -64,6 +64,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -610,20 +611,21 @@ class GraphSONSerializersV3d0 {
         }
     }
 
-    static class MetricsJacksonDeserializer extends AbstractObjectDeserializer<Metrics> {
+    static class MetricsJacksonDeserializer extends StdDeserializer<Metrics> {
         public MetricsJacksonDeserializer() {
             super(Metrics.class);
         }
 
         @Override
-        public Metrics createObject(final Map<String, Object> metricsData) {
+        public Metrics deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final Map<String, Object> metricsData = deserializationContext.readValue(jsonParser, Map.class);
             final MutableMetrics m = new MutableMetrics((String)metricsData.get(GraphSONTokens.ID), (String)metricsData.get(GraphSONTokens.NAME));
 
             m.setDuration(Math.round((Double) metricsData.get(GraphSONTokens.DURATION) * 1000000), TimeUnit.NANOSECONDS);
-            for (Map.Entry<String, Long> count : ((Map<String, Long>)metricsData.getOrDefault(GraphSONTokens.COUNTS, new HashMap<>(0))).entrySet()) {
+            for (Map.Entry<String, Long> count : ((Map<String, Long>)metricsData.getOrDefault(GraphSONTokens.COUNTS, new LinkedHashMap<>(0))).entrySet()) {
                 m.setCount(count.getKey(), count.getValue());
             }
-            for (Map.Entry<String, Long> count : ((Map<String, Long>) metricsData.getOrDefault(GraphSONTokens.ANNOTATIONS, new HashMap<>(0))).entrySet()) {
+            for (Map.Entry<String, Long> count : ((Map<String, Long>) metricsData.getOrDefault(GraphSONTokens.ANNOTATIONS, new LinkedHashMap<>(0))).entrySet()) {
                 m.setAnnotation(count.getKey(), count.getValue());
             }
             for (MutableMetrics nested : (List<MutableMetrics>)metricsData.getOrDefault(GraphSONTokens.METRICS, new ArrayList<>(0))) {
@@ -631,21 +633,33 @@ class GraphSONSerializersV3d0 {
             }
             return m;
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
-    static class TraversalMetricsJacksonDeserializer extends AbstractObjectDeserializer<TraversalMetrics> {
+    static class TraversalMetricsJacksonDeserializer extends StdDeserializer<TraversalMetrics> {
 
         public TraversalMetricsJacksonDeserializer() {
             super(TraversalMetrics.class);
         }
 
         @Override
-        public TraversalMetrics createObject(final Map<String, Object> traversalMetricsData) {
+        public TraversalMetrics deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final Map<String, Object> traversalMetricsData = deserializationContext.readValue(jsonParser, Map.class);
+
             return new DefaultTraversalMetrics(
                     Math.round((Double) traversalMetricsData.get(GraphSONTokens.DURATION) * 1000000),
                     (List<MutableMetrics>) traversalMetricsData.get(GraphSONTokens.METRICS)
             );
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
     static class TreeJacksonDeserializer extends StdDeserializer<Tree> {
@@ -703,4 +717,4 @@ class GraphSONSerializersV3d0 {
             return true;
         }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeResolverBuilder.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeResolverBuilder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeResolverBuilder.java
index 7d3d03c..0da512e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeResolverBuilder.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeResolverBuilder.java
@@ -34,11 +34,17 @@ import java.util.Collection;
  * deserializers. Contains the typeInfo level that should be provided by the GraphSONMapper.
  *
  * @author Kevin Gallardo (https://kgdo.me)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class GraphSONTypeResolverBuilder extends StdTypeResolverBuilder {
 
     private TypeInfo typeInfo;
     private String valuePropertyName;
+    private final GraphSONVersion version;
+
+    public GraphSONTypeResolverBuilder(final GraphSONVersion version) {
+        this.version = version;
+    }
 
     @Override
     public TypeDeserializer buildTypeDeserializer(final DeserializationConfig config, final JavaType baseType,
@@ -52,7 +58,9 @@ public class GraphSONTypeResolverBuilder extends StdTypeResolverBuilder {
     public TypeSerializer buildTypeSerializer(final SerializationConfig config, final JavaType baseType,
                                               final Collection<NamedType> subtypes) {
         final TypeIdResolver idRes = this.idResolver(config, baseType, subtypes, true, false);
-        return new GraphSONTypeSerializer(idRes, this.getTypeProperty(), typeInfo, valuePropertyName);
+        return version == GraphSONVersion.V2_0 ?
+                new GraphSONTypeSerializerV2d0(idRes, this.getTypeProperty(), typeInfo, valuePropertyName) :
+                new GraphSONTypeSerializerV3d0(idRes, this.getTypeProperty(), typeInfo, valuePropertyName);
     }
 
     public GraphSONTypeResolverBuilder valuePropertyName(final String valuePropertyName) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializer.java
deleted file mode 100644
index 78c670a..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializer.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.structure.io.graphson;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Operator;
-import org.apache.tinkerpop.gremlin.process.traversal.Order;
-import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.Pop;
-import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
-import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.apache.tinkerpop.shaded.jackson.annotation.JsonTypeInfo;
-import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
-import org.apache.tinkerpop.shaded.jackson.databind.BeanProperty;
-import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeIdResolver;
-import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Extension of the Jackson's default TypeSerializer. An instance of this object will be passed to the serializers
- * on which they can safely call the utility methods to serialize types and making it compatible with the version
- * 2.0 of GraphSON.
- *
- * @author Kevin Gallardo (https://kgdo.me)
- */
-public class GraphSONTypeSerializer extends TypeSerializer {
-
-    private final TypeIdResolver idRes;
-    private final String propertyName;
-    private final TypeInfo typeInfo;
-    private final String valuePropertyName;
-    private final Map<Class, Class> classMap = new HashMap<>();
-
-    GraphSONTypeSerializer(final TypeIdResolver idRes, final String propertyName, final TypeInfo typeInfo,
-                           final String valuePropertyName) {
-        this.idRes = idRes;
-        this.propertyName = propertyName;
-        this.typeInfo = typeInfo;
-        this.valuePropertyName = valuePropertyName;
-    }
-
-    @Override
-    public TypeSerializer forProperty(final BeanProperty beanProperty) {
-        return this;
-    }
-
-    @Override
-    public JsonTypeInfo.As getTypeInclusion() {
-        return null;
-    }
-
-    @Override
-    public String getPropertyName() {
-        return propertyName;
-    }
-
-    @Override
-    public TypeIdResolver getTypeIdResolver() {
-        return idRes;
-    }
-
-    @Override
-    public void writeTypePrefixForScalar(final Object o, final JsonGenerator jsonGenerator) throws IOException {
-        if (canWriteTypeId()) {
-            writeTypePrefix(jsonGenerator, getTypeIdResolver().idFromValueAndType(o, getClassFromObject(o)));
-        }
-    }
-
-    @Override
-    public void writeTypePrefixForObject(final Object o, final JsonGenerator jsonGenerator) throws IOException {
-        jsonGenerator.writeStartObject();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(Map);
-    }
-
-    @Override
-    public void writeTypePrefixForArray(final Object o, final JsonGenerator jsonGenerator) throws IOException {
-        jsonGenerator.writeStartArray();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(List);
-    }
-
-    @Override
-    public void writeTypeSuffixForScalar(final Object o, final JsonGenerator jsonGenerator) throws IOException {
-        if (canWriteTypeId()) {
-            writeTypeSuffix(jsonGenerator);
-        }
-    }
-
-    @Override
-    public void writeTypeSuffixForObject(final Object o, final JsonGenerator jsonGenerator) throws IOException {
-        jsonGenerator.writeEndObject();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(Map);
-    }
-
-    @Override
-    public void writeTypeSuffixForArray(final Object o, final JsonGenerator jsonGenerator) throws IOException {
-        jsonGenerator.writeEndArray();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(List);
-    }
-
-    @Override
-    public void writeCustomTypePrefixForScalar(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
-        if (canWriteTypeId()) {
-            writeTypePrefix(jsonGenerator, s);
-        }
-    }
-
-    @Override
-    public void writeCustomTypePrefixForObject(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
-        jsonGenerator.writeStartObject();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(s);
-    }
-
-    @Override
-    public void writeCustomTypePrefixForArray(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
-        jsonGenerator.writeStartArray();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypePrefix(s);
-    }
-
-    @Override
-    public void writeCustomTypeSuffixForScalar(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
-        if (canWriteTypeId()) {
-            writeTypeSuffix(jsonGenerator);
-        }
-    }
-
-    @Override
-    public void writeCustomTypeSuffixForObject(final Object o, final JsonGenerator jsonGenerator, final String s) throws IOException {
-        jsonGenerator.writeEndObject();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(s);
-    }
-
-    @Override
-    public void writeCustomTypeSuffixForArray(final Object o, final JsonGenerator jsonGenerator,final  String s) throws IOException {
-        jsonGenerator.writeEndArray();
-        // TODO: FULL_TYPES should be implemented here as : if (fullTypesModeEnabled()) writeTypeSuffix(s);
-    }
-
-    private boolean canWriteTypeId() {
-        return typeInfo != null
-                && typeInfo == TypeInfo.PARTIAL_TYPES;
-    }
-
-    private void writeTypePrefix(final JsonGenerator jsonGenerator, final String s) throws IOException {
-        jsonGenerator.writeStartObject();
-        jsonGenerator.writeStringField(this.getPropertyName(), s);
-        jsonGenerator.writeFieldName(this.valuePropertyName);
-    }
-
-    private void writeTypeSuffix(final JsonGenerator jsonGenerator) throws IOException {
-        jsonGenerator.writeEndObject();
-    }
-
-    /**
-     *  We force only **one** translation of a Java object to a domain specific object. i.e. users register typeIDs
-     *  and serializers/deserializers for the predefined types we have in the spec. Graph, Vertex, Edge,
-     *  VertexProperty, etc... And **not** their implementations (TinkerGraph, DetachedVertex, TinkerEdge, etc..)
-    */
-    private Class getClassFromObject(final Object o) {
-        final Class c = o.getClass();
-        if (classMap.containsKey(c))
-            return classMap.get(c);
-
-        final Class mapped;
-        if (Vertex.class.isAssignableFrom(c))
-            mapped = Vertex.class;
-        else if (Edge.class.isAssignableFrom(c))
-            mapped = Edge.class;
-        else if (Path.class.isAssignableFrom(c))
-            mapped = Path.class;
-        else if (VertexProperty.class.isAssignableFrom(c))
-            mapped = VertexProperty.class;
-        else if (Metrics.class.isAssignableFrom(c))
-            mapped = Metrics.class;
-        else if (TraversalMetrics.class.isAssignableFrom(c))
-            mapped = TraversalMetrics.class;
-        else if (Property.class.isAssignableFrom(c))
-            mapped = Property.class;
-        else if (ByteBuffer.class.isAssignableFrom(c))
-            mapped = ByteBuffer.class;
-        else if (InetAddress.class.isAssignableFrom(c))
-            mapped = InetAddress.class;
-        else if (Traverser.class.isAssignableFrom(c))
-            mapped = Traverser.class;
-        else if (Lambda.class.isAssignableFrom(c))
-            mapped = Lambda.class;
-        else if (VertexProperty.Cardinality.class.isAssignableFrom(c))
-            mapped = VertexProperty.Cardinality.class;
-        else if (Column.class.isAssignableFrom(c))
-            mapped = Column.class;
-        else if (Direction.class.isAssignableFrom(c))
-            mapped = Direction.class;
-        else if (Operator.class.isAssignableFrom(c))
-            mapped = Operator.class;
-        else if (Order.class.isAssignableFrom(c))
-            mapped = Order.class;
-        else if (Pop.class.isAssignableFrom(c))
-            mapped = Pop.class;
-        else if (SackFunctions.Barrier.class.isAssignableFrom(c))
-            mapped = SackFunctions.Barrier.class;
-        else if (TraversalOptionParent.Pick.class.isAssignableFrom(c))
-            mapped = TraversalOptionParent.Pick.class;
-        else if (Scope.class.isAssignableFrom(c))
-            mapped = Scope.class;
-        else if (T.class.isAssignableFrom(c))
-            mapped = T.class;
-        else
-            mapped = c;
-
-        classMap.put(c, mapped);
-        return mapped;
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV2d0.java
new file mode 100644
index 0000000..993f110
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV2d0.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
+import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeIdResolver;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * GraphSON 2.0 {@code TypeSerializer}.
+ *
+ * @author Kevin Gallardo (https://kgdo.me)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONTypeSerializerV2d0 extends AbstractGraphSONTypeSerializer {
+
+    GraphSONTypeSerializerV2d0(final TypeIdResolver idRes, final String propertyName, final TypeInfo typeInfo,
+                               final String valuePropertyName) {
+        super(idRes, propertyName, typeInfo, valuePropertyName);
+    }
+
+    @Override
+    protected Class getClassFromObject(final Object o) {
+        final Class c = o.getClass();
+        if (classMap.containsKey(c))
+            return classMap.get(c);
+
+        final Class mapped;
+        if (Vertex.class.isAssignableFrom(c))
+            mapped = Vertex.class;
+        else if (Edge.class.isAssignableFrom(c))
+            mapped = Edge.class;
+        else if (Path.class.isAssignableFrom(c))
+            mapped = Path.class;
+        else if (VertexProperty.class.isAssignableFrom(c))
+            mapped = VertexProperty.class;
+        else if (Metrics.class.isAssignableFrom(c))
+            mapped = Metrics.class;
+        else if (TraversalMetrics.class.isAssignableFrom(c))
+            mapped = TraversalMetrics.class;
+        else if (Property.class.isAssignableFrom(c))
+            mapped = Property.class;
+        else if (ByteBuffer.class.isAssignableFrom(c))
+            mapped = ByteBuffer.class;
+        else if (InetAddress.class.isAssignableFrom(c))
+            mapped = InetAddress.class;
+        else if (Traverser.class.isAssignableFrom(c))
+            mapped = Traverser.class;
+        else if (Lambda.class.isAssignableFrom(c))
+            mapped = Lambda.class;
+        else if (VertexProperty.Cardinality.class.isAssignableFrom(c))
+            mapped = VertexProperty.Cardinality.class;
+        else if (Column.class.isAssignableFrom(c))
+            mapped = Column.class;
+        else if (Direction.class.isAssignableFrom(c))
+            mapped = Direction.class;
+        else if (Operator.class.isAssignableFrom(c))
+            mapped = Operator.class;
+        else if (Order.class.isAssignableFrom(c))
+            mapped = Order.class;
+        else if (Pop.class.isAssignableFrom(c))
+            mapped = Pop.class;
+        else if (SackFunctions.Barrier.class.isAssignableFrom(c))
+            mapped = SackFunctions.Barrier.class;
+        else if (TraversalOptionParent.Pick.class.isAssignableFrom(c))
+            mapped = TraversalOptionParent.Pick.class;
+        else if (Scope.class.isAssignableFrom(c))
+            mapped = Scope.class;
+        else if (T.class.isAssignableFrom(c))
+            mapped = T.class;
+        else
+            mapped = c;
+
+        classMap.put(c, mapped);
+        return mapped;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV3d0.java
new file mode 100644
index 0000000..246d38f
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTypeSerializerV3d0.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
+import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeIdResolver;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+/**
+ * GraphSON 2.0 {@code TypeSerializer}.
+ *
+ * @author Kevin Gallardo (https://kgdo.me)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONTypeSerializerV3d0 extends AbstractGraphSONTypeSerializer {
+
+    GraphSONTypeSerializerV3d0(final TypeIdResolver idRes, final String propertyName, final TypeInfo typeInfo,
+                               final String valuePropertyName) {
+        super(idRes, propertyName, typeInfo, valuePropertyName);
+    }
+
+    @Override
+    public void writeTypePrefixForObject(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        if (o instanceof Map || o instanceof Map.Entry) {
+            writeTypePrefix(jsonGenerator, getTypeIdResolver().idFromValueAndType(o, getClassFromObject(o)));
+            jsonGenerator.writeStartArray();
+        } else {
+            jsonGenerator.writeStartObject();
+        }
+    }
+
+    @Override
+    public void writeTypeSuffixForObject(final Object o, final JsonGenerator jsonGenerator) throws IOException {
+        if (o instanceof Map || o instanceof Map.Entry) {
+            jsonGenerator.writeEndArray();
+            writeTypeSuffix(jsonGenerator);
+        } else {
+            jsonGenerator.writeEndObject();
+        }
+    }
+
+    @Override
+    protected Class getClassFromObject(final Object o) {
+        final Class c = o.getClass();
+        if (classMap.containsKey(c))
+            return classMap.get(c);
+
+        final Class mapped;
+        if (Map.class.isAssignableFrom(c))
+            mapped = Map.class;
+        else if (Map.Entry.class.isAssignableFrom(c))
+            mapped = Map.Entry.class;
+        else if (Vertex.class.isAssignableFrom(c))
+            mapped = Vertex.class;
+        else if (Edge.class.isAssignableFrom(c))
+            mapped = Edge.class;
+        else if (Path.class.isAssignableFrom(c))
+            mapped = Path.class;
+        else if (VertexProperty.class.isAssignableFrom(c))
+            mapped = VertexProperty.class;
+        else if (Metrics.class.isAssignableFrom(c))
+            mapped = Metrics.class;
+        else if (TraversalMetrics.class.isAssignableFrom(c))
+            mapped = TraversalMetrics.class;
+        else if (Property.class.isAssignableFrom(c))
+            mapped = Property.class;
+        else if (ByteBuffer.class.isAssignableFrom(c))
+            mapped = ByteBuffer.class;
+        else if (InetAddress.class.isAssignableFrom(c))
+            mapped = InetAddress.class;
+        else if (Traverser.class.isAssignableFrom(c))
+            mapped = Traverser.class;
+        else if (Lambda.class.isAssignableFrom(c))
+            mapped = Lambda.class;
+        else if (VertexProperty.Cardinality.class.isAssignableFrom(c))
+            mapped = VertexProperty.Cardinality.class;
+        else if (Column.class.isAssignableFrom(c))
+            mapped = Column.class;
+        else if (Direction.class.isAssignableFrom(c))
+            mapped = Direction.class;
+        else if (Operator.class.isAssignableFrom(c))
+            mapped = Operator.class;
+        else if (Order.class.isAssignableFrom(c))
+            mapped = Order.class;
+        else if (Pop.class.isAssignableFrom(c))
+            mapped = Pop.class;
+        else if (SackFunctions.Barrier.class.isAssignableFrom(c))
+            mapped = SackFunctions.Barrier.class;
+        else if (TraversalOptionParent.Pick.class.isAssignableFrom(c))
+            mapped = TraversalOptionParent.Pick.class;
+        else if (Scope.class.isAssignableFrom(c))
+            mapped = Scope.class;
+        else if (T.class.isAssignableFrom(c))
+            mapped = T.class;
+        else
+            mapped = c;
+
+        classMap.put(c, mapped);
+        return mapped;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV2d0.java
index 336d11c..0d4ba53 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV2d0.java
@@ -18,10 +18,6 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.InetAddress;
@@ -45,6 +41,8 @@ import java.util.Map;
 
 /**
  * Version 2.0 of GraphSON extensions.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class GraphSONXModuleV2d0 extends GraphSONModule {
 
@@ -139,4 +137,4 @@ public final class GraphSONXModuleV2d0 extends GraphSONModule {
             return new GraphSONXModuleV2d0(normalize);
         }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV3d0.java
index 777c6c4..38caa09 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONXModuleV3d0.java
@@ -18,10 +18,6 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.InetAddress;
@@ -45,6 +41,8 @@ import java.util.Map;
 
 /**
  * Version 3.0 of GraphSON extensions.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class GraphSONXModuleV3d0 extends GraphSONModule {
 
@@ -139,4 +137,4 @@ public final class GraphSONXModuleV3d0 extends GraphSONModule {
             return new GraphSONXModuleV3d0(normalize);
         }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV3d0.java
index 1cb75e0..c1668e2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializersV3d0.java
@@ -85,6 +85,11 @@ final class JavaTimeSerializersV3d0 {
         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/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializersV3d0.java
index 816a3f7..900eeb8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializersV3d0.java
@@ -18,16 +18,22 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
-import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
-import org.apache.tinkerpop.shaded.jackson.databind.SerializationFeature;
+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.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 java.io.IOException;
-import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * GraphSON serializers for classes in {@code java.util.*} for the version 3.0 of GraphSON.
@@ -36,6 +42,31 @@ final class JavaUtilSerializersV3d0 {
 
     private JavaUtilSerializersV3d0() {}
 
+    ////////////////////////////// SERIALIZERS /////////////////////////////////
+
+    final static class MapJacksonSerializer extends StdSerializer<Map> {
+        public MapJacksonSerializer() {
+            super(Map.class);
+        }
+
+        @Override
+        public void serialize(final Map map, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            for(Map.Entry entry : (Set<Map.Entry>) map.entrySet()) {
+                jsonGenerator.writeObject(entry.getKey());
+                jsonGenerator.writeObject(entry.getValue());
+            }
+        }
+
+        @Override
+        public void serializeWithType(final Map map, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            typeSerializer.writeTypePrefixForObject(map, jsonGenerator);
+            serialize(map, jsonGenerator, serializerProvider);
+            typeSerializer.writeTypeSuffixForObject(map, jsonGenerator);
+        }
+    }
+
     final static class MapEntryJacksonSerializer extends StdSerializer<Map.Entry> {
 
         public MapEntryJacksonSerializer() {
@@ -45,41 +76,61 @@ final class JavaUtilSerializersV3d0 {
         @Override
         public void serialize(final Map.Entry entry, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
                 throws IOException {
-            jsonGenerator.writeStartObject();
-            ser(entry, jsonGenerator, serializerProvider);
-            jsonGenerator.writeEndObject();
+            jsonGenerator.writeObject(entry.getKey());
+            jsonGenerator.writeObject(entry.getValue());
         }
 
         @Override
         public void serializeWithType(final Map.Entry entry, final JsonGenerator jsonGenerator,
                                       final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
             typeSerializer.writeTypePrefixForObject(entry, jsonGenerator);
-            ser(entry, jsonGenerator, serializerProvider);
+            serialize(entry, jsonGenerator, serializerProvider);
             typeSerializer.writeTypeSuffixForObject(entry, jsonGenerator);
         }
+    }
+
+    ////////////////////////////// DESERIALIZERS /////////////////////////////////
+
+
+    static class MapJacksonDeserializer extends StdDeserializer<Map> {
+
+        protected MapJacksonDeserializer() {
+            super(Map.class);
+        }
+
+        @Override
+        public Map deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final Map<Object,Object> m = new LinkedHashMap<>();
+
+            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
+                final Object key = deserializationContext.readValue(jsonParser, Object.class);
+                jsonParser.nextToken();
+                final Object val = deserializationContext.readValue(jsonParser, Object.class);
+                m.put(key, val);
+            }
+
+            return m;
+        }
+    }
+
+    static class MapEntryJacksonDeserializer extends StdDeserializer<Map.Entry> {
+
+        protected MapEntryJacksonDeserializer() {
+            super(Map.Entry.class);
+        }
+
+        @Override
+        public Map.Entry deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final Map<Object,Object> m = new HashMap<>();
+
+            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
+                final Object key = deserializationContext.readValue(jsonParser, Object.class);
+                jsonParser.nextToken();
+                final Object val = deserializationContext.readValue(jsonParser, Object.class);
+                m.put(key, val);
+            }
 
-        private static void ser(final Map.Entry entry, final JsonGenerator jsonGenerator,
-                                final SerializerProvider serializerProvider) throws IOException {
-            // this treatment of keys is consistent with the current GraphSONKeySerializer which extends the
-            // StdKeySerializer
-            final Object key = entry.getKey();
-            final Class cls = key.getClass();
-            String k;
-            if (cls == String.class)
-                k = (String) key;
-            else if (Element.class.isAssignableFrom(cls))
-                k = ((Element) key).id().toString();
-            else if(Date.class.isAssignableFrom(cls)) {
-                if (serializerProvider.isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS))
-                    k = String.valueOf(((Date) key).getTime());
-                else
-                    k = serializerProvider.getConfig().getDateFormat().format((Date) key);
-            } else if(cls == Class.class)
-                k = ((Class) key).getName();
-            else
-                k = key.toString();
-
-            serializerProvider.defaultSerializeField(k, entry.getValue(), jsonGenerator);
+            return m.entrySet().iterator().next();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
index e4f6df9..57b6736 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.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 TraversalSerializersV3d0 {
     // 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 TraversalSerializersV3d0 {
             }
             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 TraversalSerializersV3d0 {
                 }
             }
         }
+
+        @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 TraversalSerializersV3d0 {
             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/bef05a8e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphGraphSONSerializerV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphGraphSONSerializerV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphGraphSONSerializerV3d0.java
new file mode 100644
index 0000000..9a9682c
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/star/StarGraphGraphSONSerializerV3d0.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.util.star;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONUtil;
+import org.apache.tinkerpop.gremlin.structure.util.Comparators;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+import org.apache.tinkerpop.shaded.jackson.core.JsonGenerationException;
+import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
+import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
+import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class StarGraphGraphSONSerializerV3d0 extends StdSerializer<DirectionalStarGraph> {
+    private final boolean normalize;
+    public StarGraphGraphSONSerializerV3d0(final boolean normalize) {
+        super(DirectionalStarGraph.class);
+        this.normalize = normalize;
+    }
+
+    @Override
+    public void serialize(final DirectionalStarGraph starGraph, final JsonGenerator jsonGenerator,
+                          final SerializerProvider serializerProvider) throws IOException, JsonGenerationException {
+        ser(starGraph, jsonGenerator, serializerProvider, null);
+    }
+
+    @Override
+    public void serializeWithType(final DirectionalStarGraph starGraph, final JsonGenerator jsonGenerator,
+                                  final SerializerProvider serializerProvider,
+                                  final TypeSerializer typeSerializer) throws IOException, JsonProcessingException {
+        ser(starGraph, jsonGenerator, serializerProvider, typeSerializer);
+    }
+
+    private void ser(final DirectionalStarGraph directionalStarGraph, final JsonGenerator jsonGenerator,
+                     final SerializerProvider serializerProvider,
+                     final TypeSerializer typeSerializer) throws IOException, JsonProcessingException {
+        final StarGraph starGraph = directionalStarGraph.getStarGraphToSerialize();
+        GraphSONUtil.writeStartObject(starGraph, jsonGenerator, typeSerializer);
+        GraphSONUtil.writeWithType(GraphSONTokens.ID, starGraph.starVertex.id, jsonGenerator, serializerProvider, typeSerializer);
+        jsonGenerator.writeStringField(GraphSONTokens.LABEL, starGraph.starVertex.label);
+        if (directionalStarGraph.getDirection() != null) writeEdges(directionalStarGraph, jsonGenerator, serializerProvider, typeSerializer, Direction.IN);
+        if (directionalStarGraph.getDirection() != null) writeEdges(directionalStarGraph, jsonGenerator, serializerProvider, typeSerializer, Direction.OUT);
+        if (starGraph.starVertex.vertexProperties != null && !starGraph.starVertex.vertexProperties.isEmpty()) {
+            jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+            GraphSONUtil.writeStartObject(starGraph, jsonGenerator, typeSerializer);
+            final Set<String> keys = normalize ? new TreeSet<>(starGraph.starVertex.vertexProperties.keySet()) : starGraph.starVertex.vertexProperties.keySet();
+            for (final String k : keys) {
+                final List<VertexProperty> vp = starGraph.starVertex.vertexProperties.get(k);
+                jsonGenerator.writeFieldName(k);
+                GraphSONUtil.writeStartArray(k, jsonGenerator, typeSerializer);
+
+                final List<VertexProperty> vertexProperties = normalize ?sort(vp, Comparators.PROPERTY_COMPARATOR) : vp;
+                for (final VertexProperty property : vertexProperties) {
+                    GraphSONUtil.writeStartObject(property, jsonGenerator, typeSerializer);
+                    GraphSONUtil.writeWithType(GraphSONTokens.ID, property.id(), jsonGenerator, serializerProvider, typeSerializer);
+                    GraphSONUtil.writeWithType(GraphSONTokens.VALUE, property.value(), jsonGenerator, serializerProvider, typeSerializer);
+
+                    final Iterator<Property> metaProperties = normalize ?
+                            IteratorUtils.list(property.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : property.properties();
+                    if (metaProperties.hasNext()) {
+                        jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+                        GraphSONUtil.writeStartObject(metaProperties, jsonGenerator, typeSerializer);
+
+                        while (metaProperties.hasNext()) {
+                            final Property<Object> meta = metaProperties.next();
+                            GraphSONUtil.writeWithType(meta.key(), meta.value(), jsonGenerator, serializerProvider, typeSerializer);
+                        }
+                        GraphSONUtil.writeEndObject(metaProperties, jsonGenerator, typeSerializer);
+                    }
+                    GraphSONUtil.writeEndObject(property, jsonGenerator, typeSerializer);
+                }
+                GraphSONUtil.writeEndArray(k, jsonGenerator, typeSerializer);
+            }
+            GraphSONUtil.writeEndObject(starGraph, jsonGenerator, typeSerializer);
+        }
+        GraphSONUtil.writeEndObject(starGraph, jsonGenerator, typeSerializer);
+    }
+
+    private void writeEdges(final DirectionalStarGraph directionalStarGraph, final JsonGenerator jsonGenerator,
+                            final SerializerProvider serializerProvider,
+                            final TypeSerializer typeSerializer,
+                            final Direction direction)  throws IOException, JsonProcessingException {
+        // only write edges if there are some AND if the user requested them to be serialized AND if they match
+        // the direction being serialized by the format
+        final StarGraph starGraph = directionalStarGraph.getStarGraphToSerialize();
+        final Direction edgeDirectionToSerialize = directionalStarGraph.getDirection();
+        final Map<String, List<Edge>> starEdges = direction.equals(Direction.OUT) ? starGraph.starVertex.outEdges : starGraph.starVertex.inEdges;
+        final boolean writeEdges = null != starEdges && edgeDirectionToSerialize != null
+                && (edgeDirectionToSerialize == direction || edgeDirectionToSerialize == Direction.BOTH);
+        if (writeEdges) {
+            jsonGenerator.writeFieldName(direction == Direction.IN ? GraphSONTokens.IN_E : GraphSONTokens.OUT_E);
+            GraphSONUtil.writeStartObject(directionalStarGraph, jsonGenerator, typeSerializer);
+            final Set<String> keys = normalize ? new TreeSet<>(starEdges.keySet()) : starEdges.keySet();
+            for (final String k : keys) {
+                final List<Edge> edges = starEdges.get(k);
+                jsonGenerator.writeFieldName(k);
+                GraphSONUtil.writeStartArray(k, jsonGenerator, typeSerializer);
+
+                final List<Edge> edgesToWrite = normalize ? sort(edges, Comparators.EDGE_COMPARATOR) : edges;
+                for (final Edge edge : edgesToWrite) {
+                    GraphSONUtil.writeStartObject(edge, jsonGenerator, typeSerializer);
+                    GraphSONUtil.writeWithType(GraphSONTokens.ID, edge.id(), jsonGenerator, serializerProvider, typeSerializer);
+                    GraphSONUtil.writeWithType(direction.equals(Direction.OUT) ? GraphSONTokens.IN : GraphSONTokens.OUT,
+                            direction.equals(Direction.OUT) ? edge.inVertex().id() : edge.outVertex().id(),
+                            jsonGenerator, serializerProvider, typeSerializer);
+
+                    final Iterator<Property<Object>> edgeProperties = normalize ?
+                            IteratorUtils.list(edge.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : edge.properties();
+                    if (edgeProperties.hasNext()) {
+                        jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+                        GraphSONUtil.writeStartObject(edge, jsonGenerator, typeSerializer);
+                        while (edgeProperties.hasNext()) {
+                            final Property<Object> meta = edgeProperties.next();
+                            GraphSONUtil.writeWithType(meta.key(), meta.value(), jsonGenerator, serializerProvider, typeSerializer);
+                        }
+                        GraphSONUtil.writeEndObject(edge, jsonGenerator, typeSerializer);
+                    }
+                    GraphSONUtil.writeEndObject(edge, jsonGenerator, typeSerializer);
+                }
+                GraphSONUtil.writeEndArray(k, jsonGenerator, typeSerializer);
+            }
+            GraphSONUtil.writeEndObject(directionalStarGraph, jsonGenerator, typeSerializer);
+        }
+    }
+
+    private static <S> List<S> sort(final List<S> listToSort, final Comparator comparator) {
+        Collections.sort(listToSort, comparator);
+        return listToSort;
+    }
+
+}