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/01/19 22:56:12 UTC

[24/31] tinkerpop git commit: TINKERPOP-1565 Stub out GraphSON 3.0

TINKERPOP-1565 Stub out GraphSON 3.0

Set up the new testing model and generated test files. Reverted changes on property serialization that went in as breaking changes on GraphSON 2.0 and moved them forward to 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/7db10c40
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/7db10c40
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/7db10c40

Branch: refs/heads/TINKERPOP-1565
Commit: 7db10c40cc143473eff78866d989a90df8da7206
Parents: a004162
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Jan 12 14:58:50 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jan 19 15:15:33 2017 -0500

----------------------------------------------------------------------
 .../structure/io/graphson/GraphSONMapper.java   |  71 +-
 .../structure/io/graphson/GraphSONModule.java   | 206 ++++++
 .../io/graphson/GraphSONSerializersV2d0.java    | 162 ++---
 .../io/graphson/GraphSONSerializersV3d0.java    | 632 +++++++++++++++++
 .../structure/io/graphson/GraphSONTokens.java   |   1 +
 .../structure/io/graphson/GraphSONUtil.java     |   7 +
 .../structure/io/graphson/GraphSONVersion.java  |   3 +-
 .../ser/GraphSONMessageSerializerV3d0.java      | 124 ++++
 .../ser/GraphSONMessageSerializerV3d0Test.java  | 342 ++++++++++
 .../driver/gremlin-server-modern-secure-py.yaml |   2 +-
 gremlin-server/conf/gremlin-server-classic.yaml |   2 +-
 .../conf/gremlin-server-modern-py.yaml          |   2 +-
 gremlin-server/conf/gremlin-server-modern.yaml  |   2 +-
 gremlin-server/conf/gremlin-server.yaml         |   2 +-
 gremlin-tools/gremlin-io-test/pom.xml           |  20 +-
 .../io/graphson/GraphSONCompatibility.java      |   3 +-
 .../GraphSONTypedCompatibilityTest.java         |   9 +-
 .../_3_3_0/authenticationchallenge-v3d0.json    |  12 +
 .../authenticationresponse-v2d0-partial.json    |   5 +-
 .../_3_3_0/authenticationresponse-v3d0.json     |   9 +
 .../io/graphson/_3_3_0/barrier-v3d0.json        |   4 +
 .../io/graphson/_3_3_0/bigdecimal-v3d0.json     |   4 +
 .../io/graphson/_3_3_0/biginteger-v3d0.json     |   4 +
 .../io/graphson/_3_3_0/binding-v3d0.json        |  10 +
 .../structure/io/graphson/_3_3_0/byte-v3d0.json |   4 +
 .../io/graphson/_3_3_0/bytebuffer-v3d0.json     |   4 +
 .../io/graphson/_3_3_0/bytecode-v3d0.json       |   6 +
 .../io/graphson/_3_3_0/cardinality-v3d0.json    |   4 +
 .../structure/io/graphson/_3_3_0/char-v3d0.json |   4 +
 .../io/graphson/_3_3_0/class-v3d0.json          |   4 +
 .../io/graphson/_3_3_0/column-v3d0.json         |   4 +
 .../structure/io/graphson/_3_3_0/date-v3d0.json |   4 +
 .../io/graphson/_3_3_0/direction-v3d0.json      |   4 +
 .../io/graphson/_3_3_0/double-v3d0.json         |   4 +
 .../io/graphson/_3_3_0/duration-v3d0.json       |   4 +
 .../io/graphson/_3_3_0/edge-v2d0-no-types.json  |   5 +-
 .../io/graphson/_3_3_0/edge-v2d0-partial.json   |  10 +-
 .../structure/io/graphson/_3_3_0/edge-v3d0.json |  26 +
 .../io/graphson/_3_3_0/float-v3d0.json          |   4 +
 .../io/graphson/_3_3_0/inetaddress-v3d0.json    |   4 +
 .../io/graphson/_3_3_0/instant-v3d0.json        |   4 +
 .../io/graphson/_3_3_0/integer-v3d0.json        |   4 +
 .../io/graphson/_3_3_0/lambda-v3d0.json         |   8 +
 .../io/graphson/_3_3_0/localdate-v3d0.json      |   4 +
 .../io/graphson/_3_3_0/localdatetime-v3d0.json  |   4 +
 .../io/graphson/_3_3_0/localtime-v3d0.json      |   4 +
 .../structure/io/graphson/_3_3_0/long-v3d0.json |   4 +
 .../io/graphson/_3_3_0/metrics-v3d0.json        |  54 ++
 .../io/graphson/_3_3_0/monthday-v3d0.json       |   4 +
 .../io/graphson/_3_3_0/offsetdatetime-v3d0.json |   4 +
 .../io/graphson/_3_3_0/offsettime-v3d0.json     |   4 +
 .../io/graphson/_3_3_0/operator-v3d0.json       |   4 +
 .../io/graphson/_3_3_0/order-v3d0.json          |   4 +
 .../structure/io/graphson/_3_3_0/p-v3d0.json    |  10 +
 .../structure/io/graphson/_3_3_0/pand-v3d0.json |  25 +
 .../io/graphson/_3_3_0/path-v2d0-no-types.json  |   7 -
 .../io/graphson/_3_3_0/path-v2d0-partial.json   |  28 -
 .../structure/io/graphson/_3_3_0/path-v3d0.json | 122 ++++
 .../io/graphson/_3_3_0/period-v3d0.json         |   4 +
 .../structure/io/graphson/_3_3_0/pick-v3d0.json |   4 +
 .../structure/io/graphson/_3_3_0/pop-v3d0.json  |   4 +
 .../structure/io/graphson/_3_3_0/por-v3d0.json  |  31 +
 .../graphson/_3_3_0/property-v2d0-no-types.json |  11 +-
 .../graphson/_3_3_0/property-v2d0-partial.json  |  18 -
 .../io/graphson/_3_3_0/property-v3d0.json       |  25 +
 .../io/graphson/_3_3_0/scope-v3d0.json          |   4 +
 .../_3_3_0/sessionclose-v2d0-partial.json       |   5 +-
 .../io/graphson/_3_3_0/sessionclose-v3d0.json   |  11 +
 .../_3_3_0/sessioneval-v2d0-partial.json        |   5 +-
 .../io/graphson/_3_3_0/sessioneval-v3d0.json    |  19 +
 .../_3_3_0/sessionevalaliased-v2d0-partial.json |   5 +-
 .../_3_3_0/sessionevalaliased-v3d0.json         |  22 +
 .../_3_3_0/sessionlesseval-v2d0-partial.json    |   5 +-
 .../graphson/_3_3_0/sessionlesseval-v3d0.json   |  15 +
 .../sessionlessevalaliased-v2d0-partial.json    |   5 +-
 .../_3_3_0/sessionlessevalaliased-v3d0.json     |  18 +
 .../io/graphson/_3_3_0/short-v3d0.json          |   4 +
 .../_3_3_0/standardresult-v2d0-no-types.json    |   5 -
 .../_3_3_0/standardresult-v2d0-partial.json     |  20 -
 .../io/graphson/_3_3_0/standardresult-v3d0.json |  91 +++
 .../_3_3_0/stargraph-v2d0-no-types.json         |   5 -
 .../graphson/_3_3_0/stargraph-v2d0-partial.json |  20 -
 .../io/graphson/_3_3_0/stargraph-v3d0.json      |  82 +++
 .../structure/io/graphson/_3_3_0/t-v3d0.json    |   4 +
 .../io/graphson/_3_3_0/timestamp-v3d0.json      |   4 +
 .../_3_3_0/tinkergraph-v2d0-no-types.json       |  85 ++-
 .../_3_3_0/tinkergraph-v2d0-partial.json        | 210 +++---
 .../io/graphson/_3_3_0/tinkergraph-v3d0.json    | 671 +++++++++++++++++++
 .../graphson/_3_3_0/traversalmetrics-v3d0.json  | 114 ++++
 .../_3_3_0/traverser-v2d0-no-types.json         |   5 -
 .../graphson/_3_3_0/traverser-v2d0-partial.json |  20 -
 .../io/graphson/_3_3_0/traverser-v3d0.json      |  89 +++
 .../io/graphson/_3_3_0/tree-v2d0-no-types.json  |   7 -
 .../io/graphson/_3_3_0/tree-v2d0-partial.json   |  28 -
 .../structure/io/graphson/_3_3_0/tree-v3d0.json | 137 ++++
 .../structure/io/graphson/_3_3_0/uuid-v3d0.json |   4 +
 .../graphson/_3_3_0/vertex-v2d0-no-types.json   |   5 -
 .../io/graphson/_3_3_0/vertex-v2d0-partial.json |  20 -
 .../io/graphson/_3_3_0/vertex-v3d0.json         |  80 +++
 .../_3_3_0/vertexproperty-v2d0-no-types.json    |   1 -
 .../_3_3_0/vertexproperty-v2d0-partial.json     |   4 -
 .../io/graphson/_3_3_0/vertexproperty-v3d0.json |  15 +
 .../structure/io/graphson/_3_3_0/year-v3d0.json |   4 +
 .../io/graphson/_3_3_0/yearmonth-v3d0.json      |   4 +
 .../io/graphson/_3_3_0/zoneddatetime-v3d0.json  |   4 +
 .../io/graphson/_3_3_0/zoneoffset-v3d0.json     |   4 +
 106 files changed, 3465 insertions(+), 523 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/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 f82ebb7..d442dbc 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
@@ -87,13 +87,44 @@ public class GraphSONMapper implements Mapper<ObjectMapper> {
         om.registerModule(graphSONModule);
         customModules.forEach(om::registerModule);
 
-
         // plugin external serialization modules
         if (loadCustomSerializers)
             om.findAndRegisterModules();
 
-
-        if (version == GraphSONVersion.V1_0) {
+        // graphson 3.0 only allows type - there is no option to remove embedded types
+        if (version == GraphSONVersion.V3_0 || (version == GraphSONVersion.V2_0 && typeInfo != TypeInfo.NO_TYPES)) {
+            final GraphSONTypeIdResolver graphSONTypeIdResolver = new GraphSONTypeIdResolver();
+            final TypeResolverBuilder typer = new GraphSONTypeResolverBuilder()
+                    .typesEmbedding(getTypeInfo())
+                    .valuePropertyName(GraphSONTokens.VALUEPROP)
+                    .init(JsonTypeInfo.Id.CUSTOM, graphSONTypeIdResolver)
+                    .typeProperty(GraphSONTokens.VALUETYPE);
+
+            // Registers native Java types that are supported by Jackson
+            registerJavaBaseTypes(graphSONTypeIdResolver);
+
+            // Registers the GraphSON Module's types
+            graphSONModule.getTypeDefinitions().forEach(
+                    (targetClass, typeId) -> graphSONTypeIdResolver.addCustomType(
+                            String.format("%s:%s", graphSONModule.getTypeNamespace(), typeId), targetClass));
+
+            // Register types to typeResolver for the Custom modules
+            customModules.forEach(e -> {
+                if (e instanceof TinkerPopJacksonModule) {
+                    final TinkerPopJacksonModule mod = (TinkerPopJacksonModule) e;
+                    final Map<Class, String> moduleTypeDefinitions = mod.getTypeDefinitions();
+                    if (moduleTypeDefinitions != null) {
+                        if (mod.getTypeNamespace() == null || mod.getTypeNamespace().isEmpty())
+                            throw new IllegalStateException("Cannot specify a module for GraphSON 2.0 with type definitions but without a type Domain. " +
+                                    "If no specific type domain is required, use Gremlin's default domain, \"gremlin\" but there may be collisions.");
+
+                        moduleTypeDefinitions.forEach((targetClass, typeId) -> graphSONTypeIdResolver.addCustomType(
+                                        String.format("%s:%s", mod.getTypeNamespace(), typeId), targetClass));
+                    }
+                }
+            });
+            om.setDefaultTyping(typer);
+        } else if (version == GraphSONVersion.V1_0 || version == GraphSONVersion.V2_0) {
             if (embedTypes) {
                 final TypeResolverBuilder<?> typer = new StdTypeResolverBuilder()
                         .init(JsonTypeInfo.Id.CLASS, null)
@@ -101,40 +132,6 @@ public class GraphSONMapper implements Mapper<ObjectMapper> {
                         .typeProperty(GraphSONTokens.CLASS);
                 om.setDefaultTyping(typer);
             }
-        } else if (version == GraphSONVersion.V2_0) {
-            if (typeInfo != TypeInfo.NO_TYPES) {
-                final GraphSONTypeIdResolver graphSONTypeIdResolver = new GraphSONTypeIdResolver();
-                final TypeResolverBuilder typer = new GraphSONTypeResolverBuilder()
-                        .typesEmbedding(getTypeInfo())
-                        .valuePropertyName(GraphSONTokens.VALUEPROP)
-                        .init(JsonTypeInfo.Id.CUSTOM, graphSONTypeIdResolver)
-                        .typeProperty(GraphSONTokens.VALUETYPE);
-
-                // Registers native Java types that are supported by Jackson
-                registerJavaBaseTypes(graphSONTypeIdResolver);
-
-                // Registers the GraphSON Module's types
-                graphSONModule.getTypeDefinitions().forEach(
-                        (targetClass, typeId) -> graphSONTypeIdResolver.addCustomType(
-                                String.format("%s:%s", graphSONModule.getTypeNamespace(), typeId), targetClass));
-
-                // Register types to typeResolver for the Custom modules
-                customModules.forEach(e -> {
-                    if (e instanceof TinkerPopJacksonModule) {
-                        final TinkerPopJacksonModule mod = (TinkerPopJacksonModule) e;
-                        final Map<Class, String> moduleTypeDefinitions = mod.getTypeDefinitions();
-                        if (moduleTypeDefinitions != null) {
-                            if (mod.getTypeNamespace() == null || mod.getTypeNamespace().isEmpty())
-                                throw new IllegalStateException("Cannot specify a module for GraphSON 2.0 with type definitions but without a type Domain. " +
-                                        "If no specific type domain is required, use Gremlin's default domain, \"gremlin\" but there may be collisions.");
-
-                            moduleTypeDefinitions.forEach((targetClass, typeId) -> graphSONTypeIdResolver.addCustomType(
-                                            String.format("%s:%s", mod.getTypeNamespace(), typeId), targetClass));
-                        }
-                    }
-                });
-                om.setDefaultTyping(typer);
-            }
         } else {
             throw new IllegalStateException("Unknown GraphSONVersion : " + version);
         }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/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 a061d1c..dceae6b 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
@@ -109,6 +109,212 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
     }
 
     /**
+     * Version 3.0 of GraphSON.
+     */
+    static final class GraphSONModuleV3d0 extends GraphSONModule {
+
+        private static final Map<Class, String> TYPE_DEFINITIONS = Collections.unmodifiableMap(
+                new LinkedHashMap<Class, String>() {{
+                    // Those don't have deserializers because handled by Jackson,
+                    // but we still want to rename them in GraphSON
+                    put(Integer.class, "Int32");
+                    put(Long.class, "Int64");
+                    put(Double.class, "Double");
+                    put(Float.class, "Float");
+
+                    // Tinkerpop Graph objects
+                    put(Lambda.class, "Lambda");
+                    put(Vertex.class, "Vertex");
+                    put(Edge.class, "Edge");
+                    put(Property.class, "Property");
+                    put(Path.class, "Path");
+                    put(VertexProperty.class, "VertexProperty");
+                    put(Metrics.class, "Metrics");
+                    put(TraversalMetrics.class, "TraversalMetrics");
+                    put(Traverser.class, "Traverser");
+                    put(Tree.class, "Tree");
+                    put(Bytecode.class, "Bytecode");
+                    put(Bytecode.Binding.class, "Binding");
+                    put(AndP.class, "P");
+                    put(OrP.class, "P");
+                    put(P.class, "P");
+                    Stream.of(
+                            VertexProperty.Cardinality.class,
+                            Column.class,
+                            Direction.class,
+                            Operator.class,
+                            Order.class,
+                            Pop.class,
+                            SackFunctions.Barrier.class,
+                            TraversalOptionParent.Pick.class,
+                            Scope.class,
+                            T.class).forEach(e -> put(e, e.getSimpleName()));
+                    Arrays.asList(
+                            ConnectiveStrategy.class,
+                            ElementIdStrategy.class,
+                            EventStrategy.class,
+                            HaltedTraverserStrategy.class,
+                            PartitionStrategy.class,
+                            SubgraphStrategy.class,
+                            LazyBarrierStrategy.class,
+                            MatchAlgorithmStrategy.class,
+                            AdjacentToIncidentStrategy.class,
+                            FilterRankingStrategy.class,
+                            IdentityRemovalStrategy.class,
+                            IncidentToAdjacentStrategy.class,
+                            InlineFilterStrategy.class,
+                            MatchPredicateStrategy.class,
+                            OrderLimitStrategy.class,
+                            PathProcessorStrategy.class,
+                            PathRetractionStrategy.class,
+                            RangeByIsCountStrategy.class,
+                            RepeatUnrollStrategy.class,
+                            ComputerVerificationStrategy.class,
+                            LambdaRestrictionStrategy.class,
+                            ReadOnlyStrategy.class,
+                            StandardVerificationStrategy.class,
+                            //
+                            GraphFilterStrategy.class,
+                            VertexProgramStrategy.class
+                    ).forEach(strategy -> put(strategy, strategy.getSimpleName()));
+                }});
+
+        /**
+         * Constructs a new object.
+         */
+        protected GraphSONModuleV3d0(final boolean normalize) {
+            super("graphson-3.0");
+
+            /////////////////////// SERIALIZERS ////////////////////////////
+
+            // graph
+            addSerializer(Edge.class, new GraphSONSerializersV3d0.EdgeJacksonSerializer(normalize));
+            addSerializer(Vertex.class, new GraphSONSerializersV3d0.VertexJacksonSerializer(normalize));
+            addSerializer(VertexProperty.class, new GraphSONSerializersV3d0.VertexPropertyJacksonSerializer(normalize, true));
+            addSerializer(Property.class, new GraphSONSerializersV3d0.PropertyJacksonSerializer());
+            addSerializer(Metrics.class, new GraphSONSerializersV3d0.MetricsJacksonSerializer());
+            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(Tree.class, new GraphSONSerializersV3d0.TreeJacksonSerializer());
+
+            // java.util
+            addSerializer(Map.Entry.class, new JavaUtilSerializersV2d0.MapEntryJacksonSerializer());
+
+            // need to explicitly add serializers for those types because Jackson doesn't do it at all.
+            addSerializer(Integer.class, new GraphSONSerializersV3d0.IntegerGraphSONSerializer());
+            addSerializer(Double.class, new GraphSONSerializersV3d0.DoubleGraphSONSerializer());
+
+            // traversal
+            addSerializer(Traversal.class, new GraphSONTraversalSerializersV2d0.TraversalJacksonSerializer());
+            addSerializer(Bytecode.class, new GraphSONTraversalSerializersV2d0.BytecodeJacksonSerializer());
+            Stream.of(VertexProperty.Cardinality.class,
+                    Column.class,
+                    Direction.class,
+                    Operator.class,
+                    Order.class,
+                    Pop.class,
+                    SackFunctions.Barrier.class,
+                    Scope.class,
+                    TraversalOptionParent.Pick.class,
+                    T.class).forEach(e -> addSerializer(e, new GraphSONTraversalSerializersV2d0.EnumJacksonSerializer()));
+            addSerializer(P.class, new GraphSONTraversalSerializersV2d0.PJacksonSerializer());
+            addSerializer(Lambda.class, new GraphSONTraversalSerializersV2d0.LambdaJacksonSerializer());
+            addSerializer(Bytecode.Binding.class, new GraphSONTraversalSerializersV2d0.BindingJacksonSerializer());
+            addSerializer(Traverser.class, new GraphSONTraversalSerializersV2d0.TraverserJacksonSerializer());
+            addSerializer(TraversalStrategy.class, new GraphSONTraversalSerializersV2d0.TraversalStrategyJacksonSerializer());
+
+            /////////////////////// DESERIALIZERS ////////////////////////////
+
+            // Tinkerpop Graph
+            addDeserializer(Vertex.class, new GraphSONSerializersV3d0.VertexJacksonDeserializer());
+            addDeserializer(Edge.class, new GraphSONSerializersV3d0.EdgeJacksonDeserializer());
+            addDeserializer(Property.class, new GraphSONSerializersV3d0.PropertyJacksonDeserializer());
+            addDeserializer(Path.class, new GraphSONSerializersV3d0.PathJacksonDeserializer());
+            addDeserializer(VertexProperty.class, new GraphSONSerializersV3d0.VertexPropertyJacksonDeserializer());
+            addDeserializer(Metrics.class, new GraphSONSerializersV3d0.MetricsJacksonDeserializer());
+            addDeserializer(TraversalMetrics.class, new GraphSONSerializersV3d0.TraversalMetricsJacksonDeserializer());
+            addDeserializer(Tree.class, new GraphSONSerializersV3d0.TreeJacksonDeserializer());
+
+            // numbers
+            addDeserializer(Integer.class, new GraphSONSerializersV2d0.IntegerJackonsDeserializer());
+            addDeserializer(Double.class, new GraphSONSerializersV2d0.DoubleJackonsDeserializer());
+
+            // traversal
+            addDeserializer(Bytecode.class, new GraphSONTraversalSerializersV2d0.BytecodeJacksonDeserializer());
+            addDeserializer(Bytecode.Binding.class, new GraphSONTraversalSerializersV2d0.BindingJacksonDeserializer());
+            Stream.of(VertexProperty.Cardinality.values(),
+                    Column.values(),
+                    Direction.values(),
+                    Operator.values(),
+                    Order.values(),
+                    Pop.values(),
+                    SackFunctions.Barrier.values(),
+                    Scope.values(),
+                    TraversalOptionParent.Pick.values(),
+                    T.values()).flatMap(Stream::of).forEach(e -> addDeserializer(e.getClass(), new GraphSONTraversalSerializersV2d0.EnumJacksonDeserializer(e.getDeclaringClass())));
+            addDeserializer(P.class, new GraphSONTraversalSerializersV2d0.PJacksonDeserializer());
+            addDeserializer(Lambda.class, new GraphSONTraversalSerializersV2d0.LambdaJacksonDeserializer());
+            addDeserializer(Traverser.class, new GraphSONTraversalSerializersV2d0.TraverserJacksonDeserializer());
+            Arrays.asList(
+                    ConnectiveStrategy.class,
+                    ElementIdStrategy.class,
+                    EventStrategy.class,
+                    HaltedTraverserStrategy.class,
+                    PartitionStrategy.class,
+                    SubgraphStrategy.class,
+                    LazyBarrierStrategy.class,
+                    MatchAlgorithmStrategy.class,
+                    AdjacentToIncidentStrategy.class,
+                    FilterRankingStrategy.class,
+                    IdentityRemovalStrategy.class,
+                    IncidentToAdjacentStrategy.class,
+                    InlineFilterStrategy.class,
+                    MatchPredicateStrategy.class,
+                    OrderLimitStrategy.class,
+                    PathProcessorStrategy.class,
+                    PathRetractionStrategy.class,
+                    RangeByIsCountStrategy.class,
+                    RepeatUnrollStrategy.class,
+                    ComputerVerificationStrategy.class,
+                    LambdaRestrictionStrategy.class,
+                    ReadOnlyStrategy.class,
+                    StandardVerificationStrategy.class,
+                    //
+                    GraphFilterStrategy.class,
+                    VertexProgramStrategy.class
+            ).forEach(strategy -> addDeserializer(strategy, new GraphSONTraversalSerializersV2d0.TraversalStrategyProxyJacksonDeserializer(strategy)));
+        }
+
+        public static Builder build() {
+            return new Builder();
+        }
+
+        @Override
+        public Map<Class, String> getTypeDefinitions() {
+            return TYPE_DEFINITIONS;
+        }
+
+        @Override
+        public String getTypeNamespace() {
+            return GraphSONTokens.GREMLIN_TYPE_NAMESPACE;
+        }
+
+        static final class Builder implements GraphSONModuleBuilder {
+
+            private Builder() {
+            }
+
+            @Override
+            public GraphSONModule create(final boolean normalize) {
+                return new GraphSONModuleV3d0(normalize);
+            }
+
+        }
+    }
+
+    /**
      * Version 2.0 of GraphSON.
      */
     static final class GraphSONModuleV2d0 extends GraphSONModule {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/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 824fc7f..f8f4cd1 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
@@ -54,7 +54,6 @@ import org.javatuples.Pair;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -64,6 +63,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
+import static org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONUtil.safeWriteObjectField;
+
 /**
  * GraphSON serializers for graph-based objects such as vertices, edges, properties, and paths. These serializers
  * present a generalized way to serialize the implementations of core interfaces.
@@ -100,34 +101,22 @@ class GraphSONSerializersV2d0 {
         }
 
         private void writeProperties(final Vertex vertex, final JsonGenerator jsonGenerator) throws IOException {
-            if (vertex.keys().isEmpty())
+            if (vertex.keys().size() == 0)
                 return;
             jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
             jsonGenerator.writeStartObject();
 
             final List<String> keys = normalize ?
                     IteratorUtils.list(vertex.keys().iterator(), Comparator.naturalOrder()) : new ArrayList<>(vertex.keys());
-            for (final String key : keys) {
+            for (String key : keys) {
                 final Iterator<VertexProperty<Object>> vertexProperties = normalize ?
                         IteratorUtils.list(vertex.properties(key), Comparators.PROPERTY_COMPARATOR).iterator() : vertex.properties(key);
                 if (vertexProperties.hasNext()) {
                     jsonGenerator.writeFieldName(key);
+
                     jsonGenerator.writeStartArray();
                     while (vertexProperties.hasNext()) {
-                        final VertexProperty<?> vertexProperty = vertexProperties.next();
-                        jsonGenerator.writeStartObject();
-                        jsonGenerator.writeObjectField(GraphSONTokens.ID, vertexProperty.id());
-                        jsonGenerator.writeObjectField(GraphSONTokens.VALUE, vertexProperty.value());
-                        if (!vertexProperty.keys().isEmpty()) {
-                            jsonGenerator.writeObjectFieldStart(GraphSONTokens.PROPERTIES);
-                            final Iterator<Property<?>> properties = (Iterator) vertexProperty.properties();
-                            while (properties.hasNext()) {
-                                final Property<?> property = properties.next();
-                                jsonGenerator.writeObjectField(property.key(), property.value());
-                            }
-                            jsonGenerator.writeEndObject();
-                        }
-                        jsonGenerator.writeEndObject();
+                        jsonGenerator.writeObject(vertexProperties.next());
                     }
                     jsonGenerator.writeEndArray();
                 }
@@ -164,15 +153,13 @@ class GraphSONSerializersV2d0 {
         }
 
         private void writeProperties(final Edge edge, final JsonGenerator jsonGenerator) throws IOException {
-            final Iterator<Property<Object>> edgeProperties = normalize ?
+            final Iterator<Property<Object>> elementProperties = normalize ?
                     IteratorUtils.list(edge.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : edge.properties();
-            if (edgeProperties.hasNext()) {
+            if (elementProperties.hasNext()) {
                 jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+
                 jsonGenerator.writeStartObject();
-                while (edgeProperties.hasNext()) {
-                    final Property<?> property = edgeProperties.next();
-                    jsonGenerator.writeObjectField(property.key(), property.value());
-                }
+                elementProperties.forEachRemaining(prop -> safeWriteObjectField(jsonGenerator, prop.key(), prop));
                 jsonGenerator.writeEndObject();
             }
         }
@@ -188,25 +175,8 @@ class GraphSONSerializersV2d0 {
         public void serialize(final Property property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
                 throws IOException {
             jsonGenerator.writeStartObject();
-            jsonGenerator.writeStringField(GraphSONTokens.KEY, property.key());
+            jsonGenerator.writeObjectField(GraphSONTokens.KEY, property.key());
             jsonGenerator.writeObjectField(GraphSONTokens.VALUE, property.value());
-            if (property.element() instanceof VertexProperty) {
-                VertexProperty vertexProperty = (VertexProperty) property.element();
-                jsonGenerator.writeObjectFieldStart(GraphSONTokens.VERTEX_PROPERTY);
-                jsonGenerator.writeObjectField(GraphSONTokens.ID, vertexProperty.id());
-                jsonGenerator.writeStringField(GraphSONTokens.LABEL, vertexProperty.label());
-                jsonGenerator.writeObjectField(GraphSONTokens.VALUE, vertexProperty.value());
-                jsonGenerator.writeObjectField(GraphSONTokens.VERTEX, vertexProperty.element().id());
-                jsonGenerator.writeEndObject();
-            } else if (property.element() instanceof Edge) {
-                Edge edge = (Edge) property.element();
-                jsonGenerator.writeObjectFieldStart(GraphSONTokens.EDGE);
-                jsonGenerator.writeObjectField(GraphSONTokens.ID, edge.id());
-                jsonGenerator.writeStringField(GraphSONTokens.LABEL, edge.label());
-                jsonGenerator.writeObjectField(GraphSONTokens.IN, edge.inVertex().id());
-                jsonGenerator.writeObjectField(GraphSONTokens.OUT, edge.outVertex().id());
-                jsonGenerator.writeEndObject();
-            }
             jsonGenerator.writeEndObject();
         }
     }
@@ -223,46 +193,44 @@ class GraphSONSerializersV2d0 {
         }
 
         @Override
-        public void serialize(final VertexProperty vertexProperty, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+        public void serialize(final VertexProperty property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
                 throws IOException {
             jsonGenerator.writeStartObject();
 
-            jsonGenerator.writeObjectField(GraphSONTokens.ID, vertexProperty.id());
-            jsonGenerator.writeObjectField(GraphSONTokens.VALUE, vertexProperty.value());
-            if (null != vertexProperty.element())
-                jsonGenerator.writeObjectField(GraphSONTokens.VERTEX, vertexProperty.element().id());
-            if (this.includeLabel)
-                jsonGenerator.writeStringField(GraphSONTokens.LABEL, vertexProperty.label());
-            tryWriteMetaProperties(vertexProperty, jsonGenerator, normalize);
+            jsonGenerator.writeObjectField(GraphSONTokens.ID, property.id());
+            jsonGenerator.writeObjectField(GraphSONTokens.VALUE, property.value());
+            if (includeLabel)
+                jsonGenerator.writeStringField(GraphSONTokens.LABEL, property.label());
+            tryWriteMetaProperties(property, jsonGenerator, normalize);
 
             jsonGenerator.writeEndObject();
         }
 
-        private static void tryWriteMetaProperties(final VertexProperty vertexProperty, final JsonGenerator jsonGenerator,
+        private static void tryWriteMetaProperties(final VertexProperty property, final JsonGenerator jsonGenerator,
                                                    final boolean normalize) throws IOException {
             // when "detached" you can't check features of the graph it detached from so it has to be
             // treated differently from a regular VertexProperty implementation.
-            if (vertexProperty instanceof DetachedVertexProperty) {
+            if (property instanceof DetachedVertexProperty) {
                 // only write meta properties key if they exist
-                if (vertexProperty.properties().hasNext()) {
-                    writeMetaProperties(vertexProperty, jsonGenerator, normalize);
+                if (property.properties().hasNext()) {
+                    writeMetaProperties(property, jsonGenerator, normalize);
                 }
             } else {
                 // still attached - so we can check the features to see if it's worth even trying to write the
                 // meta properties key
-                if (vertexProperty.graph().features().vertex().supportsMetaProperties() && vertexProperty.properties().hasNext()) {
-                    writeMetaProperties(vertexProperty, jsonGenerator, normalize);
+                if (property.graph().features().vertex().supportsMetaProperties() && property.properties().hasNext()) {
+                    writeMetaProperties(property, jsonGenerator, normalize);
                 }
             }
         }
 
-        private static void writeMetaProperties(final VertexProperty vertexProperty, final JsonGenerator jsonGenerator,
+        private static void writeMetaProperties(final VertexProperty property, final JsonGenerator jsonGenerator,
                                                 final boolean normalize) throws IOException {
             jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
             jsonGenerator.writeStartObject();
 
             final Iterator<Property<Object>> metaProperties = normalize ?
-                    IteratorUtils.list((Iterator<Property<Object>>) vertexProperty.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : vertexProperty.properties();
+                    IteratorUtils.list((Iterator<Property<Object>>) property.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : property.properties();
             while (metaProperties.hasNext()) {
                 final Property<Object> metaProperty = metaProperties.next();
                 jsonGenerator.writeObjectField(metaProperty.key(), metaProperty.value());
@@ -358,7 +326,7 @@ class GraphSONSerializersV2d0 {
         @Override
         public void serialize(final Integer integer, final JsonGenerator jsonGenerator,
                               final SerializerProvider serializerProvider) throws IOException {
-            jsonGenerator.writeNumber(integer.intValue());
+            jsonGenerator.writeNumber(((Integer) integer).intValue());
         }
     }
 
@@ -459,7 +427,7 @@ class GraphSONSerializersV2d0 {
         public Vertex createObject(final Map<String, Object> vertexData) {
             return new DetachedVertex(
                     vertexData.get(GraphSONTokens.ID),
-                    (String) vertexData.getOrDefault(GraphSONTokens.LABEL, Vertex.DEFAULT_LABEL),
+                    vertexData.get(GraphSONTokens.LABEL).toString(),
                     (Map<String, Object>) vertexData.get(GraphSONTokens.PROPERTIES)
             );
         }
@@ -475,10 +443,10 @@ class GraphSONSerializersV2d0 {
         public Edge createObject(final Map<String, Object> edgeData) {
             return new DetachedEdge(
                     edgeData.get(GraphSONTokens.ID),
-                    (String) edgeData.getOrDefault(GraphSONTokens.LABEL, Edge.DEFAULT_LABEL),
-                    (Map<String, Object>) edgeData.get(GraphSONTokens.PROPERTIES),
-                    Pair.with(edgeData.get(GraphSONTokens.OUT), (String) edgeData.getOrDefault(GraphSONTokens.OUT_LABEL, Vertex.DEFAULT_LABEL)),
-                    Pair.with(edgeData.get(GraphSONTokens.IN), (String) edgeData.getOrDefault(GraphSONTokens.IN_LABEL, Vertex.DEFAULT_LABEL))
+                    edgeData.get(GraphSONTokens.LABEL).toString(),
+                    (Map) edgeData.get(GraphSONTokens.PROPERTIES),
+                    Pair.with(edgeData.get(GraphSONTokens.OUT), edgeData.get(GraphSONTokens.OUT_LABEL).toString()),
+                    Pair.with(edgeData.get(GraphSONTokens.IN), edgeData.get(GraphSONTokens.IN_LABEL).toString())
             );
         }
     }
@@ -491,41 +459,9 @@ class GraphSONSerializersV2d0 {
 
         @Override
         public Property createObject(final Map<String, Object> propData) {
-            Element element = null;
-            if (propData.containsKey(GraphSONTokens.VERTEX_PROPERTY)) {
-                final Map<String, Object> elementData = (Map<String, Object>) propData.get(GraphSONTokens.VERTEX_PROPERTY);
-                element = new VertexPropertyJacksonDeserializer().createObject(elementData);
-            } else if (propData.containsKey(GraphSONTokens.EDGE)) {
-                final Map<String, Object> elementData = (Map<String, Object>) propData.get(GraphSONTokens.EDGE);
-                element = new EdgeJacksonDeserializer().createObject(elementData);
-            }
-            return null != element ? // graphson-non-embedded is treated differently, but since this is a hard coded embedding...
-                    new DetachedProperty<>((String) propData.get(GraphSONTokens.KEY), propData.get(GraphSONTokens.VALUE), element) :
-                    new DetachedProperty<>((String) propData.get(GraphSONTokens.KEY), propData.get(GraphSONTokens.VALUE));
-        }
-    }
-
-    static class VertexPropertyJacksonDeserializer extends AbstractObjectDeserializer<VertexProperty> {
-
-        protected VertexPropertyJacksonDeserializer() {
-            super(VertexProperty.class);
-        }
-
-        @Override
-        public VertexProperty createObject(final Map<String, Object> propData) {
-            return propData.containsKey(GraphSONTokens.VERTEX) ?
-                    new DetachedVertexProperty<>(
-                            propData.get(GraphSONTokens.ID),
-                            (String) propData.get(GraphSONTokens.LABEL),
-                            propData.get(GraphSONTokens.VALUE),
-                            (Map<String, Object>) propData.get(GraphSONTokens.PROPERTIES),
-                            new DetachedVertex(propData.get(GraphSONTokens.VERTEX), Vertex.DEFAULT_LABEL, null)) :
-                    new DetachedVertexProperty<>(
-                            propData.get(GraphSONTokens.ID),
-                            (String) propData.get(GraphSONTokens.LABEL),
-                            propData.get(GraphSONTokens.VALUE),
-                            (Map<String, Object>) propData.get(GraphSONTokens.PROPERTIES));
-
+            return new DetachedProperty(
+                    (String) propData.get(GraphSONTokens.KEY),
+                    propData.get(GraphSONTokens.VALUE));
         }
     }
 
@@ -549,6 +485,23 @@ class GraphSONSerializersV2d0 {
         }
     }
 
+    static class VertexPropertyJacksonDeserializer extends AbstractObjectDeserializer<VertexProperty> {
+
+        protected VertexPropertyJacksonDeserializer() {
+            super(VertexProperty.class);
+        }
+
+        @Override
+        public VertexProperty createObject(final Map<String, Object> propData) {
+            return new DetachedVertexProperty(
+                    propData.get(GraphSONTokens.ID),
+                    (String) propData.get(GraphSONTokens.LABEL),
+                    propData.get(GraphSONTokens.VALUE),
+                    (Map) propData.get(GraphSONTokens.PROPERTIES)
+            );
+        }
+    }
+
     static class MetricsJacksonDeserializer extends AbstractObjectDeserializer<Metrics> {
         public MetricsJacksonDeserializer() {
             super(Metrics.class);
@@ -556,16 +509,16 @@ class GraphSONSerializersV2d0 {
 
         @Override
         public Metrics createObject(final Map<String, Object> metricsData) {
-            final MutableMetrics m = new MutableMetrics((String) metricsData.get(GraphSONTokens.ID), (String) metricsData.get(GraphSONTokens.NAME));
+            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, Collections.emptyMap())).entrySet()) {
+            for (Map.Entry<String, Long> count : ((Map<String, Long>)metricsData.getOrDefault(GraphSONTokens.COUNTS, new HashMap<>(0))).entrySet()) {
                 m.setCount(count.getKey(), count.getValue());
             }
-            for (Map.Entry<String, Long> count : ((Map<String, Long>) metricsData.getOrDefault(GraphSONTokens.ANNOTATIONS, Collections.emptyMap())).entrySet()) {
+            for (Map.Entry<String, Long> count : ((Map<String, Long>) metricsData.getOrDefault(GraphSONTokens.ANNOTATIONS, new HashMap<>(0))).entrySet()) {
                 m.setAnnotation(count.getKey(), count.getValue());
             }
-            for (MutableMetrics nested : (List<MutableMetrics>) metricsData.getOrDefault(GraphSONTokens.METRICS, Collections.emptyList())) {
+            for (MutableMetrics nested : (List<MutableMetrics>)metricsData.getOrDefault(GraphSONTokens.METRICS, new ArrayList<>(0))) {
                 m.addNested(nested);
             }
             return m;
@@ -627,7 +580,4 @@ class GraphSONSerializersV2d0 {
             return jsonParser.getDoubleValue();
         }
     }
-}
-
-
-
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/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
new file mode 100644
index 0000000..165e7e1
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java
@@ -0,0 +1,632 @@
+/*
+ * 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.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalMetrics;
+import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
+import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.Comparators;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
+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.JsonParser;
+import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
+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.StdKeySerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
+import org.javatuples.Pair;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * GraphSON serializers for graph-based objects such as vertices, edges, properties, and paths. These serializers
+ * present a generalized way to serialize the implementations of core interfaces.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class GraphSONSerializersV3d0 {
+
+    private GraphSONSerializersV3d0() {
+    }
+
+    ////////////////////////////// SERIALIZERS /////////////////////////////////
+
+    final static class VertexJacksonSerializer extends StdScalarSerializer<Vertex> {
+
+        private final boolean normalize;
+
+        public VertexJacksonSerializer(final boolean normalize) {
+            super(Vertex.class);
+            this.normalize = normalize;
+        }
+
+        @Override
+        public void serialize(final Vertex vertex, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            jsonGenerator.writeStartObject();
+
+            jsonGenerator.writeObjectField(GraphSONTokens.ID, vertex.id());
+            jsonGenerator.writeStringField(GraphSONTokens.LABEL, vertex.label());
+            writeProperties(vertex, jsonGenerator);
+
+            jsonGenerator.writeEndObject();
+
+        }
+
+        private void writeProperties(final Vertex vertex, final JsonGenerator jsonGenerator) throws IOException {
+            if (vertex.keys().isEmpty())
+                return;
+            jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+            jsonGenerator.writeStartObject();
+
+            final List<String> keys = normalize ?
+                    IteratorUtils.list(vertex.keys().iterator(), Comparator.naturalOrder()) : new ArrayList<>(vertex.keys());
+            for (final String key : keys) {
+                final Iterator<VertexProperty<Object>> vertexProperties = normalize ?
+                        IteratorUtils.list(vertex.properties(key), Comparators.PROPERTY_COMPARATOR).iterator() : vertex.properties(key);
+                if (vertexProperties.hasNext()) {
+                    jsonGenerator.writeFieldName(key);
+                    jsonGenerator.writeStartArray();
+                    while (vertexProperties.hasNext()) {
+                        final VertexProperty<?> vertexProperty = vertexProperties.next();
+                        jsonGenerator.writeStartObject();
+                        jsonGenerator.writeObjectField(GraphSONTokens.ID, vertexProperty.id());
+                        jsonGenerator.writeObjectField(GraphSONTokens.VALUE, vertexProperty.value());
+                        if (!vertexProperty.keys().isEmpty()) {
+                            jsonGenerator.writeObjectFieldStart(GraphSONTokens.PROPERTIES);
+                            final Iterator<Property<?>> properties = (Iterator) vertexProperty.properties();
+                            while (properties.hasNext()) {
+                                final Property<?> property = properties.next();
+                                jsonGenerator.writeObjectField(property.key(), property.value());
+                            }
+                            jsonGenerator.writeEndObject();
+                        }
+                        jsonGenerator.writeEndObject();
+                    }
+                    jsonGenerator.writeEndArray();
+                }
+            }
+
+            jsonGenerator.writeEndObject();
+        }
+    }
+
+    final static class EdgeJacksonSerializer extends StdScalarSerializer<Edge> {
+
+        private final boolean normalize;
+
+        public EdgeJacksonSerializer(final boolean normalize) {
+            super(Edge.class);
+            this.normalize = normalize;
+        }
+
+
+        @Override
+        public void serialize(final Edge edge, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            jsonGenerator.writeStartObject();
+
+            jsonGenerator.writeObjectField(GraphSONTokens.ID, edge.id());
+            jsonGenerator.writeStringField(GraphSONTokens.LABEL, edge.label());
+            jsonGenerator.writeStringField(GraphSONTokens.IN_LABEL, edge.inVertex().label());
+            jsonGenerator.writeStringField(GraphSONTokens.OUT_LABEL, edge.outVertex().label());
+            jsonGenerator.writeObjectField(GraphSONTokens.IN, edge.inVertex().id());
+            jsonGenerator.writeObjectField(GraphSONTokens.OUT, edge.outVertex().id());
+            writeProperties(edge, jsonGenerator);
+
+            jsonGenerator.writeEndObject();
+        }
+
+        private void writeProperties(final Edge edge, final JsonGenerator jsonGenerator) throws IOException {
+            final Iterator<Property<Object>> edgeProperties = normalize ?
+                    IteratorUtils.list(edge.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : edge.properties();
+            if (edgeProperties.hasNext()) {
+                jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+                jsonGenerator.writeStartObject();
+                while (edgeProperties.hasNext()) {
+                    final Property<?> property = edgeProperties.next();
+                    jsonGenerator.writeObjectField(property.key(), property.value());
+                }
+                jsonGenerator.writeEndObject();
+            }
+        }
+    }
+
+    final static class PropertyJacksonSerializer extends StdScalarSerializer<Property> {
+
+        public PropertyJacksonSerializer() {
+            super(Property.class);
+        }
+
+        @Override
+        public void serialize(final Property property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            jsonGenerator.writeStartObject();
+            jsonGenerator.writeStringField(GraphSONTokens.KEY, property.key());
+            jsonGenerator.writeObjectField(GraphSONTokens.VALUE, property.value());
+            if (property.element() instanceof VertexProperty) {
+                VertexProperty vertexProperty = (VertexProperty) property.element();
+                jsonGenerator.writeObjectFieldStart(GraphSONTokens.VERTEX_PROPERTY);
+                jsonGenerator.writeObjectField(GraphSONTokens.ID, vertexProperty.id());
+                jsonGenerator.writeStringField(GraphSONTokens.LABEL, vertexProperty.label());
+                jsonGenerator.writeObjectField(GraphSONTokens.VALUE, vertexProperty.value());
+                jsonGenerator.writeObjectField(GraphSONTokens.VERTEX, vertexProperty.element().id());
+                jsonGenerator.writeEndObject();
+            } else if (property.element() instanceof Edge) {
+                Edge edge = (Edge) property.element();
+                jsonGenerator.writeObjectFieldStart(GraphSONTokens.EDGE);
+                jsonGenerator.writeObjectField(GraphSONTokens.ID, edge.id());
+                jsonGenerator.writeStringField(GraphSONTokens.LABEL, edge.label());
+                jsonGenerator.writeObjectField(GraphSONTokens.IN, edge.inVertex().id());
+                jsonGenerator.writeObjectField(GraphSONTokens.OUT, edge.outVertex().id());
+                jsonGenerator.writeEndObject();
+            }
+            jsonGenerator.writeEndObject();
+        }
+    }
+
+    final static class VertexPropertyJacksonSerializer extends StdScalarSerializer<VertexProperty> {
+
+        private final boolean normalize;
+        private final boolean includeLabel;
+
+        public VertexPropertyJacksonSerializer(final boolean normalize, final boolean includeLabel) {
+            super(VertexProperty.class);
+            this.normalize = normalize;
+            this.includeLabel = includeLabel;
+        }
+
+        @Override
+        public void serialize(final VertexProperty vertexProperty, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            jsonGenerator.writeStartObject();
+
+            jsonGenerator.writeObjectField(GraphSONTokens.ID, vertexProperty.id());
+            jsonGenerator.writeObjectField(GraphSONTokens.VALUE, vertexProperty.value());
+            if (null != vertexProperty.element())
+                jsonGenerator.writeObjectField(GraphSONTokens.VERTEX, vertexProperty.element().id());
+            if (this.includeLabel)
+                jsonGenerator.writeStringField(GraphSONTokens.LABEL, vertexProperty.label());
+            tryWriteMetaProperties(vertexProperty, jsonGenerator, normalize);
+
+            jsonGenerator.writeEndObject();
+        }
+
+        private static void tryWriteMetaProperties(final VertexProperty vertexProperty, final JsonGenerator jsonGenerator,
+                                                   final boolean normalize) throws IOException {
+            // when "detached" you can't check features of the graph it detached from so it has to be
+            // treated differently from a regular VertexProperty implementation.
+            if (vertexProperty instanceof DetachedVertexProperty) {
+                // only write meta properties key if they exist
+                if (vertexProperty.properties().hasNext()) {
+                    writeMetaProperties(vertexProperty, jsonGenerator, normalize);
+                }
+            } else {
+                // still attached - so we can check the features to see if it's worth even trying to write the
+                // meta properties key
+                if (vertexProperty.graph().features().vertex().supportsMetaProperties() && vertexProperty.properties().hasNext()) {
+                    writeMetaProperties(vertexProperty, jsonGenerator, normalize);
+                }
+            }
+        }
+
+        private static void writeMetaProperties(final VertexProperty vertexProperty, final JsonGenerator jsonGenerator,
+                                                final boolean normalize) throws IOException {
+            jsonGenerator.writeFieldName(GraphSONTokens.PROPERTIES);
+            jsonGenerator.writeStartObject();
+
+            final Iterator<Property<Object>> metaProperties = normalize ?
+                    IteratorUtils.list((Iterator<Property<Object>>) vertexProperty.properties(), Comparators.PROPERTY_COMPARATOR).iterator() : vertexProperty.properties();
+            while (metaProperties.hasNext()) {
+                final Property<Object> metaProperty = metaProperties.next();
+                jsonGenerator.writeObjectField(metaProperty.key(), metaProperty.value());
+            }
+
+            jsonGenerator.writeEndObject();
+        }
+
+
+    }
+
+    final static class PathJacksonSerializer extends StdScalarSerializer<Path> {
+
+        public PathJacksonSerializer() {
+            super(Path.class);
+        }
+
+        @Override
+        public void serialize(final Path path, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException, JsonGenerationException {
+            jsonGenerator.writeStartObject();
+
+            jsonGenerator.writeObjectField(GraphSONTokens.LABELS, path.labels());
+            jsonGenerator.writeObjectField(GraphSONTokens.OBJECTS, path.objects());
+
+            jsonGenerator.writeEndObject();
+        }
+    }
+
+    final static class TreeJacksonSerializer extends StdScalarSerializer<Tree> {
+
+        public TreeJacksonSerializer() {
+            super(Tree.class);
+        }
+
+        @Override
+        public void serialize(final Tree tree, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException, JsonGenerationException {
+            jsonGenerator.writeStartArray();
+            final Set<Map.Entry<Element, Tree>> set = tree.entrySet();
+            for (Map.Entry<Element, Tree> entry : set) {
+                jsonGenerator.writeStartObject();
+                jsonGenerator.writeObjectField(GraphSONTokens.KEY, entry.getKey());
+                jsonGenerator.writeObjectField(GraphSONTokens.VALUE, entry.getValue());
+                jsonGenerator.writeEndObject();
+            }
+            jsonGenerator.writeEndArray();
+        }
+    }
+
+    final static class TraversalExplanationJacksonSerializer extends StdSerializer<TraversalExplanation> {
+        public TraversalExplanationJacksonSerializer() {
+            super(TraversalExplanation.class);
+        }
+
+        @Override
+        public void serialize(final TraversalExplanation traversalExplanation, final JsonGenerator jsonGenerator,
+                              final SerializerProvider serializerProvider) throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ORIGINAL, getStepsAsList(traversalExplanation.getOriginalTraversal()));
+
+            final List<Pair<TraversalStrategy, Traversal.Admin<?, ?>>> strategyTraversals = traversalExplanation.getStrategyTraversals();
+
+            final List<Map<String, Object>> intermediates = new ArrayList<>();
+            for (final Pair<TraversalStrategy, Traversal.Admin<?, ?>> pair : strategyTraversals) {
+                final Map<String, Object> intermediate = new HashMap<>();
+                intermediate.put(GraphSONTokens.STRATEGY, pair.getValue0().toString());
+                intermediate.put(GraphSONTokens.CATEGORY, pair.getValue0().getTraversalCategory().getSimpleName());
+                intermediate.put(GraphSONTokens.TRAVERSAL, getStepsAsList(pair.getValue1()));
+                intermediates.add(intermediate);
+            }
+            m.put(GraphSONTokens.INTERMEDIATE, intermediates);
+
+            if (strategyTraversals.isEmpty())
+                m.put(GraphSONTokens.FINAL, getStepsAsList(traversalExplanation.getOriginalTraversal()));
+            else
+                m.put(GraphSONTokens.FINAL, getStepsAsList(strategyTraversals.get(strategyTraversals.size() - 1).getValue1()));
+
+            jsonGenerator.writeObject(m);
+        }
+
+        private List<String> getStepsAsList(final Traversal.Admin<?, ?> t) {
+            final List<String> steps = new ArrayList<>();
+            t.getSteps().iterator().forEachRemaining(s -> steps.add(s.toString()));
+            return steps;
+        }
+    }
+
+    final static class IntegerGraphSONSerializer extends StdScalarSerializer<Integer> {
+        public IntegerGraphSONSerializer() {
+            super(Integer.class);
+        }
+
+        @Override
+        public void serialize(final Integer integer, final JsonGenerator jsonGenerator,
+                              final SerializerProvider serializerProvider) throws IOException {
+            jsonGenerator.writeNumber(integer.intValue());
+        }
+    }
+
+    final static class DoubleGraphSONSerializer extends StdScalarSerializer<Double> {
+        public DoubleGraphSONSerializer() {
+            super(Double.class);
+        }
+
+        @Override
+        public void serialize(final Double doubleValue, final JsonGenerator jsonGenerator,
+                              final SerializerProvider serializerProvider) throws IOException {
+            jsonGenerator.writeNumber(doubleValue);
+        }
+    }
+
+    final static class TraversalMetricsJacksonSerializer extends StdScalarSerializer<TraversalMetrics> {
+        public TraversalMetricsJacksonSerializer() {
+            super(TraversalMetrics.class);
+        }
+
+        @Override
+        public void serialize(final TraversalMetrics traversalMetrics, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            // creation of the map enables all the fields to be properly written with their type if required
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.DURATION, traversalMetrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d);
+            final List<Metrics> metrics = new ArrayList<>();
+            metrics.addAll(traversalMetrics.getMetrics());
+            m.put(GraphSONTokens.METRICS, metrics);
+
+            jsonGenerator.writeObject(m);
+        }
+    }
+
+    final static class MetricsJacksonSerializer extends StdScalarSerializer<Metrics> {
+        public MetricsJacksonSerializer() {
+            super(Metrics.class);
+        }
+
+        @Override
+        public void serialize(final Metrics metrics, final JsonGenerator jsonGenerator,
+                              final SerializerProvider serializerProvider) throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, metrics.getId());
+            m.put(GraphSONTokens.NAME, metrics.getName());
+            m.put(GraphSONTokens.COUNTS, metrics.getCounts());
+            m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d);
+
+            if (!metrics.getAnnotations().isEmpty()) {
+                m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations());
+            }
+            if (!metrics.getNested().isEmpty()) {
+                final List<Metrics> nested = new ArrayList<>();
+                metrics.getNested().forEach(it -> nested.add(it));
+                m.put(GraphSONTokens.METRICS, nested);
+            }
+            jsonGenerator.writeObject(m);
+        }
+    }
+
+
+    /**
+     * Maps in the JVM can have {@link Object} as a key, but in JSON they must be a {@link String}.
+     */
+    final static class GraphSONKeySerializer extends StdKeySerializer {
+
+        @Override
+        public void serialize(final Object o, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException {
+            ser(o, jsonGenerator, serializerProvider);
+        }
+
+        @Override
+        public void serializeWithType(final Object o, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(o, jsonGenerator, serializerProvider);
+        }
+
+        private void ser(final Object o, final JsonGenerator jsonGenerator,
+                         final SerializerProvider serializerProvider) throws IOException {
+            if (Element.class.isAssignableFrom(o.getClass()))
+                jsonGenerator.writeFieldName((((Element) o).id()).toString());
+            else
+                super.serialize(o, jsonGenerator, serializerProvider);
+        }
+    }
+
+
+    //////////////////////////// DESERIALIZERS ///////////////////////////
+
+
+    static class VertexJacksonDeserializer extends AbstractObjectDeserializer<Vertex> {
+
+        public VertexJacksonDeserializer() {
+            super(Vertex.class);
+        }
+
+        @Override
+        public Vertex createObject(final Map<String, Object> vertexData) {
+            return new DetachedVertex(
+                    vertexData.get(GraphSONTokens.ID),
+                    (String) vertexData.getOrDefault(GraphSONTokens.LABEL, Vertex.DEFAULT_LABEL),
+                    (Map<String, Object>) vertexData.get(GraphSONTokens.PROPERTIES)
+            );
+        }
+    }
+
+    static class EdgeJacksonDeserializer extends AbstractObjectDeserializer<Edge> {
+
+        public EdgeJacksonDeserializer() {
+            super(Edge.class);
+        }
+
+        @Override
+        public Edge createObject(final Map<String, Object> edgeData) {
+            return new DetachedEdge(
+                    edgeData.get(GraphSONTokens.ID),
+                    (String) edgeData.getOrDefault(GraphSONTokens.LABEL, Edge.DEFAULT_LABEL),
+                    (Map<String, Object>) edgeData.get(GraphSONTokens.PROPERTIES),
+                    Pair.with(edgeData.get(GraphSONTokens.OUT), (String) edgeData.getOrDefault(GraphSONTokens.OUT_LABEL, Vertex.DEFAULT_LABEL)),
+                    Pair.with(edgeData.get(GraphSONTokens.IN), (String) edgeData.getOrDefault(GraphSONTokens.IN_LABEL, Vertex.DEFAULT_LABEL))
+            );
+        }
+    }
+
+    static class PropertyJacksonDeserializer extends AbstractObjectDeserializer<Property> {
+
+        public PropertyJacksonDeserializer() {
+            super(Property.class);
+        }
+
+        @Override
+        public Property createObject(final Map<String, Object> propData) {
+            Element element = null;
+            if (propData.containsKey(GraphSONTokens.VERTEX_PROPERTY)) {
+                final Map<String, Object> elementData = (Map<String, Object>) propData.get(GraphSONTokens.VERTEX_PROPERTY);
+                element = new VertexPropertyJacksonDeserializer().createObject(elementData);
+            } else if (propData.containsKey(GraphSONTokens.EDGE)) {
+                final Map<String, Object> elementData = (Map<String, Object>) propData.get(GraphSONTokens.EDGE);
+                element = new EdgeJacksonDeserializer().createObject(elementData);
+            }
+            return null != element ? // graphson-non-embedded is treated differently, but since this is a hard coded embedding...
+                    new DetachedProperty<>((String) propData.get(GraphSONTokens.KEY), propData.get(GraphSONTokens.VALUE), element) :
+                    new DetachedProperty<>((String) propData.get(GraphSONTokens.KEY), propData.get(GraphSONTokens.VALUE));
+        }
+    }
+
+    static class VertexPropertyJacksonDeserializer extends AbstractObjectDeserializer<VertexProperty> {
+
+        protected VertexPropertyJacksonDeserializer() {
+            super(VertexProperty.class);
+        }
+
+        @Override
+        public VertexProperty createObject(final Map<String, Object> propData) {
+            return propData.containsKey(GraphSONTokens.VERTEX) ?
+                    new DetachedVertexProperty<>(
+                            propData.get(GraphSONTokens.ID),
+                            (String) propData.get(GraphSONTokens.LABEL),
+                            propData.get(GraphSONTokens.VALUE),
+                            (Map<String, Object>) propData.get(GraphSONTokens.PROPERTIES),
+                            new DetachedVertex(propData.get(GraphSONTokens.VERTEX), Vertex.DEFAULT_LABEL, null)) :
+                    new DetachedVertexProperty<>(
+                            propData.get(GraphSONTokens.ID),
+                            (String) propData.get(GraphSONTokens.LABEL),
+                            propData.get(GraphSONTokens.VALUE),
+                            (Map<String, Object>) propData.get(GraphSONTokens.PROPERTIES));
+
+        }
+    }
+
+    static class PathJacksonDeserializer extends AbstractObjectDeserializer<Path> {
+
+        public PathJacksonDeserializer() {
+            super(Path.class);
+        }
+
+        @Override
+        public Path createObject(final Map<String, Object> pathData) {
+            final Path p = MutablePath.make();
+
+            final List labels = (List) pathData.get(GraphSONTokens.LABELS);
+            final List objects = (List) pathData.get(GraphSONTokens.OBJECTS);
+
+            for (int i = 0; i < objects.size(); i++) {
+                p.extend(objects.get(i), new HashSet((List) labels.get(i)));
+            }
+            return p;
+        }
+    }
+
+    static class MetricsJacksonDeserializer extends AbstractObjectDeserializer<Metrics> {
+        public MetricsJacksonDeserializer() {
+            super(Metrics.class);
+        }
+
+        @Override
+        public Metrics createObject(final Map<String, Object> metricsData) {
+            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, Collections.emptyMap())).entrySet()) {
+                m.setCount(count.getKey(), count.getValue());
+            }
+            for (Map.Entry<String, Long> count : ((Map<String, Long>) metricsData.getOrDefault(GraphSONTokens.ANNOTATIONS, Collections.emptyMap())).entrySet()) {
+                m.setAnnotation(count.getKey(), count.getValue());
+            }
+            for (MutableMetrics nested : (List<MutableMetrics>) metricsData.getOrDefault(GraphSONTokens.METRICS, Collections.emptyList())) {
+                m.addNested(nested);
+            }
+            return m;
+        }
+    }
+
+    static class TraversalMetricsJacksonDeserializer extends AbstractObjectDeserializer<TraversalMetrics> {
+
+        public TraversalMetricsJacksonDeserializer() {
+            super(TraversalMetrics.class);
+        }
+
+        @Override
+        public TraversalMetrics createObject(final Map<String, Object> traversalMetricsData) {
+            return new DefaultTraversalMetrics(
+                    Math.round((Double) traversalMetricsData.get(GraphSONTokens.DURATION) * 1000000),
+                    (List<MutableMetrics>) traversalMetricsData.get(GraphSONTokens.METRICS)
+            );
+        }
+    }
+
+    static class TreeJacksonDeserializer extends StdDeserializer<Tree> {
+
+        public TreeJacksonDeserializer() {
+            super(Tree.class);
+        }
+
+        @Override
+        public Tree deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final List<Map> data = deserializationContext.readValue(jsonParser, List.class);
+            final Tree t = new Tree();
+            for (Map<String, Object> entry : data) {
+                t.put(entry.get(GraphSONTokens.KEY), entry.get(GraphSONTokens.VALUE));
+            }
+            return t;
+        }
+    }
+
+    static class IntegerJackonsDeserializer extends StdDeserializer<Integer> {
+
+        protected IntegerJackonsDeserializer() {
+            super(Integer.class);
+        }
+
+        @Override
+        public Integer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            return jsonParser.getIntValue();
+        }
+    }
+
+    static class DoubleJackonsDeserializer extends StdDeserializer<Double> {
+
+        protected DoubleJackonsDeserializer() {
+            super(Double.class);
+        }
+
+        @Override
+        public Double deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            return jsonParser.getDoubleValue();
+        }
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTokens.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTokens.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTokens.java
index d804f0b..10e36e0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTokens.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTokens.java
@@ -36,6 +36,7 @@ public final class GraphSONTokens {
     public static final String KEY = "key";
     public static final String EDGE = "edge";
     public static final String EDGES = "edges";
+    public static final String ELEMENT = "ELEMENT";
     public static final String VERTEX = "vertex";
     public static final String VERTEX_PROPERTY = "vertexProperty";
     public static final String VERTICES = "vertices";

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUtil.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUtil.java
index 97292af..710c2bc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONUtil.java
@@ -86,4 +86,11 @@ public final class GraphSONUtil {
             jsonGenerator.writeEndArray();
     }
 
+    static void safeWriteObjectField(final JsonGenerator jsonGenerator, final String key, final Object value) {
+        try {
+            jsonGenerator.writeObjectField(key, value);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVersion.java
index 7740b06..cb163e7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVersion.java
@@ -25,7 +25,8 @@ package org.apache.tinkerpop.gremlin.structure.io.graphson;
  */
 public enum GraphSONVersion {
     V1_0(GraphSONModule.GraphSONModuleV1d0.build(), "1.0"),
-    V2_0(GraphSONModule.GraphSONModuleV2d0.build(), "2.0");
+    V2_0(GraphSONModule.GraphSONModuleV2d0.build(), "2.0"),
+    V3_0(GraphSONModule.GraphSONModuleV3d0.build(), "3.0");
 
     private final GraphSONModule.GraphSONModuleBuilder builder;
     private final String versionNumber;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7db10c40/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java
new file mode 100644
index 0000000..f6f2fc8
--- /dev/null
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java
@@ -0,0 +1,124 @@
+/*
+ * 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.driver.ser;
+
+import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Serialize results to JSON with version 3.0.x schema and the extended module.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class GraphSONMessageSerializerV3d0 extends AbstractGraphSONMessageSerializerV2d0 implements MessageTextSerializer {
+    private static final Logger logger = LoggerFactory.getLogger(GraphSONMessageSerializerV3d0.class);
+    private static final String MIME_TYPE = SerTokens.MIME_JSON;
+
+    private static byte[] header;
+
+    static {
+        final ByteBuffer buffer = ByteBuffer.allocate(MIME_TYPE.length() + 1);
+        buffer.put((byte) MIME_TYPE.length());
+        buffer.put(MIME_TYPE.getBytes());
+        header = buffer.array();
+    }
+
+    public GraphSONMessageSerializerV3d0() {
+        super();
+    }
+
+    public GraphSONMessageSerializerV3d0(final GraphSONMapper mapper) {
+        super(mapper);
+    }
+
+    @Override
+    public String[] mimeTypesSupported() {
+        return new String[]{MIME_TYPE, "application/json"};
+    }
+
+    @Override
+    GraphSONMapper.Builder configureBuilder(final GraphSONMapper.Builder builder) {
+        // override the 2.0 in AbstractGraphSONMessageSerializerV2d0
+        return builder.typeInfo(TypeInfo.PARTIAL_TYPES).version(GraphSONVersion.V3_0);
+    }
+
+    @Override
+    byte[] obtainHeader() {
+        return header;
+    }
+
+    @Override
+    public ResponseMessage deserializeResponse(final String msg) throws SerializationException {
+        try {
+            final Map<String, Object> responseData = mapper.readValue(msg, mapTypeReference);
+            final Map<String, Object> status = (Map<String, Object>) responseData.get(SerTokens.TOKEN_STATUS);
+            final Map<String, Object> result = (Map<String, Object>) responseData.get(SerTokens.TOKEN_RESULT);
+            return ResponseMessage.build(UUID.fromString(responseData.get(SerTokens.TOKEN_REQUEST).toString()))
+                    .code(ResponseStatusCode.getFromValue((Integer) status.get(SerTokens.TOKEN_CODE)))
+                    .statusMessage(status.get(SerTokens.TOKEN_MESSAGE).toString())
+                    .statusAttributes((Map<String, Object>) status.get(SerTokens.TOKEN_ATTRIBUTES))
+                    .result(result.get(SerTokens.TOKEN_DATA))
+                    .responseMetaData((Map<String, Object>) result.get(SerTokens.TOKEN_META))
+                    .create();
+        } catch (Exception ex) {
+            logger.warn("Response [{}] could not be deserialized by {}.", msg, AbstractGraphSONMessageSerializerV2d0.class.getName());
+            throw new SerializationException(ex);
+        }
+    }
+
+    @Override
+    public String serializeResponseAsString(final ResponseMessage responseMessage) throws SerializationException {
+        try {
+            return mapper.writeValueAsString(responseMessage);
+        } catch (Exception ex) {
+            logger.warn("Response [{}] could not be serialized by {}.", responseMessage.toString(), AbstractGraphSONMessageSerializerV2d0.class.getName());
+            throw new SerializationException(ex);
+        }
+    }
+
+    @Override
+    public RequestMessage deserializeRequest(final String msg) throws SerializationException {
+        try {
+            return mapper.readValue(msg, RequestMessage.class);
+        } catch (Exception ex) {
+            logger.warn("Request [{}] could not be deserialized by {}.", msg, AbstractGraphSONMessageSerializerV2d0.class.getName());
+            throw new SerializationException(ex);
+        }
+    }
+
+    @Override
+    public String serializeRequestAsString(final RequestMessage requestMessage) throws SerializationException {
+        try {
+            return mapper.writeValueAsString(requestMessage);
+        } catch (Exception ex) {
+            logger.warn("Request [{}] could not be serialized by {}.", requestMessage.toString(), AbstractGraphSONMessageSerializerV2d0.class.getName());
+            throw new SerializationException(ex);
+        }
+    }
+}