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 2015/02/12 14:01:36 UTC

[10/77] [partial] incubator-tinkerpop git commit: moved com/tinkerpop directories to org/apache/tinkerpop

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriterHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriterHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriterHelper.java
new file mode 100644
index 0000000..912286d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriterHelper.java
@@ -0,0 +1,377 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphml;
+
+import org.apache.commons.lang.StringUtils;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.util.Stack;
+
+/**
+ * A wrapper for the IndentingXMLStreamWriter class by Kohsuke Kawaguchi
+ */
+class GraphMLWriterHelper {
+    /**
+     * Delegating {@link javax.xml.stream.XMLStreamWriter}.
+     *
+     * @author Kohsuke Kawaguchi
+     */
+    private abstract static class DelegatingXMLStreamWriter implements XMLStreamWriter {
+        private final XMLStreamWriter writer;
+
+        public DelegatingXMLStreamWriter(final XMLStreamWriter writer) {
+            this.writer = writer;
+        }
+
+        @Override
+        public void writeStartElement(final String localName) throws XMLStreamException {
+            writer.writeStartElement(localName);
+        }
+
+        @Override
+        public void writeStartElement(final String namespaceURI, final String localName) throws XMLStreamException {
+            writer.writeStartElement(namespaceURI, localName);
+        }
+
+        @Override
+        public void writeStartElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+            writer.writeStartElement(prefix, localName, namespaceURI);
+        }
+
+        @Override
+        public void writeEmptyElement(final String namespaceURI, final String localName) throws XMLStreamException {
+            writer.writeEmptyElement(namespaceURI, localName);
+        }
+
+        @Override
+        public void writeEmptyElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+            writer.writeEmptyElement(prefix, localName, namespaceURI);
+        }
+
+        @Override
+        public void writeEmptyElement(final String localName) throws XMLStreamException {
+            writer.writeEmptyElement(localName);
+        }
+
+        @Override
+        public void writeEndElement() throws XMLStreamException {
+            writer.writeEndElement();
+        }
+
+        @Override
+        public void writeEndDocument() throws XMLStreamException {
+            writer.writeEndDocument();
+        }
+
+        @Override
+        public void close() throws XMLStreamException {
+            writer.close();
+        }
+
+        @Override
+        public void flush() throws XMLStreamException {
+            writer.flush();
+        }
+
+        @Override
+        public void writeAttribute(final String localName, final String value) throws XMLStreamException {
+            writer.writeAttribute(localName, value);
+        }
+
+        @Override
+        public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String value) throws XMLStreamException {
+            writer.writeAttribute(prefix, namespaceURI, localName, value);
+        }
+
+        @Override
+        public void writeAttribute(final String namespaceURI, final String localName, final String value) throws XMLStreamException {
+            writer.writeAttribute(namespaceURI, localName, value);
+        }
+
+        @Override
+        public void writeNamespace(final String prefix, final String namespaceURI) throws XMLStreamException {
+            writer.writeNamespace(prefix, namespaceURI);
+        }
+
+        @Override
+        public void writeDefaultNamespace(final String namespaceURI) throws XMLStreamException {
+            writer.writeDefaultNamespace(namespaceURI);
+        }
+
+        @Override
+        public void writeComment(final String data) throws XMLStreamException {
+            writer.writeComment(data);
+        }
+
+        @Override
+        public void writeProcessingInstruction(final String target) throws XMLStreamException {
+            writer.writeProcessingInstruction(target);
+        }
+
+        @Override
+        public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+            writer.writeProcessingInstruction(target, data);
+        }
+
+        @Override
+        public void writeCData(final String data) throws XMLStreamException {
+            writer.writeCData(data);
+        }
+
+        @Override
+        public void writeDTD(final String dtd) throws XMLStreamException {
+            writer.writeDTD(dtd);
+        }
+
+        @Override
+        public void writeEntityRef(final String name) throws XMLStreamException {
+            writer.writeEntityRef(name);
+        }
+
+        @Override
+        public void writeStartDocument() throws XMLStreamException {
+            writer.writeStartDocument();
+        }
+
+        @Override
+        public void writeStartDocument(final String version) throws XMLStreamException {
+            writer.writeStartDocument(version);
+        }
+
+        @Override
+        public void writeStartDocument(final String encoding, final String version) throws XMLStreamException {
+            writer.writeStartDocument(encoding, version);
+        }
+
+        @Override
+        public void writeCharacters(final String text) throws XMLStreamException {
+            writer.writeCharacters(text);
+        }
+
+        @Override
+        public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+            writer.writeCharacters(text, start, len);
+        }
+
+        @Override
+        public String getPrefix(final String uri) throws XMLStreamException {
+            return writer.getPrefix(uri);
+        }
+
+        @Override
+        public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
+            writer.setPrefix(prefix, uri);
+        }
+
+        @Override
+        public void setDefaultNamespace(final String uri) throws XMLStreamException {
+            writer.setDefaultNamespace(uri);
+        }
+
+        @Override
+        public void setNamespaceContext(final NamespaceContext context) throws XMLStreamException {
+            writer.setNamespaceContext(context);
+        }
+
+        @Override
+        public NamespaceContext getNamespaceContext() {
+            return writer.getNamespaceContext();
+        }
+
+        @Override
+        public Object getProperty(final String name) throws IllegalArgumentException {
+            return writer.getProperty(name);
+        }
+    }
+
+    /**
+     * @author Kohsuke Kawaguchi
+     */
+    public static class IndentingXMLStreamWriter extends DelegatingXMLStreamWriter {
+        private final static Object SEEN_NOTHING = new Object();
+        private final static Object SEEN_ELEMENT = new Object();
+        private final static Object SEEN_DATA = new Object();
+
+        private Object state = SEEN_NOTHING;
+        private Stack<Object> stateStack = new Stack<>();
+
+        private String indentStep = "  ";
+        private static final String lineSeparator = System.getProperty("line.separator", "\n");
+        private int depth = 0;
+
+        public IndentingXMLStreamWriter(final XMLStreamWriter writer) {
+            super(writer);
+        }
+
+        /**
+         * Return the current indent step.
+         * <p/>
+         * <p>Return the current indent step: each start tag will be
+         * indented by this number of spaces times the number of
+         * ancestors that the element has.</p>
+         *
+         * @return The number of spaces in each indentation step,
+         * or 0 or less for no indentation.
+         * @see #setIndentStep(int)
+         * @deprecated Only return the length of the indent string.
+         */
+        public int getIndentStep() {
+            return indentStep.length();
+        }
+
+
+        /**
+         * Set the current indent step.
+         *
+         * @param indentStep The new indent step (0 or less for no
+         *                   indentation).
+         * @see #getIndentStep()
+         * @deprecated Should use the version that takes string.
+         */
+        public void setIndentStep(int indentStep) {
+            this.indentStep = StringUtils.repeat(" ", indentStep);
+        }
+
+        public void setIndentStep(final String s) {
+            this.indentStep = s;
+        }
+
+        private void onStartElement() throws XMLStreamException {
+            stateStack.push(SEEN_ELEMENT);
+            state = SEEN_NOTHING;
+            if (depth > 0) {
+                super.writeCharacters(lineSeparator);
+            }
+            doIndent();
+            depth++;
+        }
+
+        private void onEndElement() throws XMLStreamException {
+            depth--;
+            if (state == SEEN_ELEMENT) {
+                super.writeCharacters(lineSeparator);
+                doIndent();
+            }
+            state = stateStack.pop();
+        }
+
+        private void onEmptyElement() throws XMLStreamException {
+            state = SEEN_ELEMENT;
+            if (depth > 0) {
+                super.writeCharacters(lineSeparator);
+            }
+            doIndent();
+        }
+
+        /**
+         * Print indentation for the current level.
+         *
+         * @throws javax.xml.stream.XMLStreamException If there is an error writing the indentation characters, or if a filter
+         *                                             further down the chain raises an exception.
+         */
+        private void doIndent() throws XMLStreamException {
+            if (depth > 0) {
+                for (int i = 0; i < depth; i++)
+                    super.writeCharacters(indentStep);
+            }
+        }
+
+
+        @Override
+        public void writeStartDocument() throws XMLStreamException {
+            super.writeStartDocument();
+            super.writeCharacters(lineSeparator);
+        }
+
+        @Override
+        public void writeStartDocument(final String version) throws XMLStreamException {
+            super.writeStartDocument(version);
+            super.writeCharacters(lineSeparator);
+        }
+
+        @Override
+        public void writeStartDocument(final String encoding, final String version) throws XMLStreamException {
+            super.writeStartDocument(encoding, version);
+            super.writeCharacters(lineSeparator);
+        }
+
+        @Override
+        public void writeStartElement(final String localName) throws XMLStreamException {
+            onStartElement();
+            super.writeStartElement(localName);
+        }
+
+        @Override
+        public void writeStartElement(final String namespaceURI, final String localName) throws XMLStreamException {
+            onStartElement();
+            super.writeStartElement(namespaceURI, localName);
+        }
+
+        @Override
+        public void writeStartElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+            onStartElement();
+            super.writeStartElement(prefix, localName, namespaceURI);
+        }
+
+        @Override
+        public void writeEmptyElement(final String namespaceURI, final String localName) throws XMLStreamException {
+            onEmptyElement();
+            super.writeEmptyElement(namespaceURI, localName);
+        }
+
+        @Override
+        public void writeEmptyElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+            onEmptyElement();
+            super.writeEmptyElement(prefix, localName, namespaceURI);
+        }
+
+        @Override
+        public void writeEmptyElement(final String localName) throws XMLStreamException {
+            onEmptyElement();
+            super.writeEmptyElement(localName);
+        }
+
+        @Override
+        public void writeEndElement() throws XMLStreamException {
+            onEndElement();
+            super.writeEndElement();
+        }
+
+        @Override
+        public void writeCharacters(final String text) throws XMLStreamException {
+            state = SEEN_DATA;
+            super.writeCharacters(text);
+        }
+
+        @Override
+        public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+            state = SEEN_DATA;
+            super.writeCharacters(text, start, len);
+        }
+
+        @Override
+        public void writeCData(final String data) throws XMLStreamException {
+            state = SEEN_DATA;
+            super.writeCData(data);
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONGraph.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONGraph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONGraph.java
new file mode 100644
index 0000000..cbe9570
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONGraph.java
@@ -0,0 +1,90 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.tinkerpop.gremlin.structure.Graph;
+import com.tinkerpop.gremlin.structure.util.Comparators;
+import com.tinkerpop.gremlin.util.function.FunctionUtils;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class GraphSONGraph {
+    private final Graph graphToSerialize;
+
+    public GraphSONGraph(final Graph graphToSerialize) {
+        this.graphToSerialize = graphToSerialize;
+    }
+
+    public Graph getGraphToSerialize() {
+        return graphToSerialize;
+    }
+
+    static class GraphJacksonSerializer extends StdSerializer<GraphSONGraph> {
+        private final boolean normalize;
+
+        public GraphJacksonSerializer(final boolean normalize) {
+            super(GraphSONGraph.class);
+            this.normalize = normalize;
+        }
+
+        @Override
+        public void serialize(final GraphSONGraph graphSONGraph, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(graphSONGraph, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final GraphSONGraph graphSONGraph, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(graphSONGraph, jsonGenerator);
+        }
+
+        private void ser(final GraphSONGraph graphSONGraph, final JsonGenerator jsonGenerator) throws IOException {
+            final Graph g = graphSONGraph.getGraphToSerialize();
+            jsonGenerator.writeStartObject();
+
+            if (g.features().graph().variables().supportsVariables())
+                jsonGenerator.writeObjectField(GraphSONTokens.VARIABLES, new HashMap<>(g.variables().asMap()));
+
+            jsonGenerator.writeArrayFieldStart(GraphSONTokens.VERTICES);
+            if (normalize)
+                g.V().order().by(Comparators.VERTEX_COMPARATOR).forEachRemaining(FunctionUtils.wrapConsumer(jsonGenerator::writeObject));
+            else
+                g.iterators().vertexIterator().forEachRemaining(FunctionUtils.wrapConsumer(jsonGenerator::writeObject));
+            jsonGenerator.writeEndArray();
+
+            jsonGenerator.writeArrayFieldStart(GraphSONTokens.EDGES);
+            if (normalize)
+                g.E().order().by(Comparators.EDGE_COMPARATOR).forEachRemaining(FunctionUtils.wrapConsumer(jsonGenerator::writeObject));
+            else
+                g.iterators().edgeIterator().forEachRemaining(FunctionUtils.wrapConsumer(jsonGenerator::writeObject));
+            jsonGenerator.writeEndArray();
+
+            jsonGenerator.writeEndObject();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/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
new file mode 100644
index 0000000..de541e4
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapper.java
@@ -0,0 +1,132 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
+import com.tinkerpop.gremlin.structure.io.Mapper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An extension to the standard Jackson {@code ObjectMapper} which automatically registers the standard
+ * {@link GraphSONModule} for serializing {@link com.tinkerpop.gremlin.structure.Graph} elements.  This class
+ * can be used for generalized JSON serialization tasks that require meeting GraphSON standards.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONMapper implements Mapper<ObjectMapper> {
+
+    private final List<SimpleModule> customModules;
+    private final boolean loadCustomSerializers;
+    private final boolean normalize;
+    private final boolean embedTypes;
+
+    private GraphSONMapper(final List<SimpleModule> customModules, final boolean loadCustomSerializers,
+                           final boolean normalize, final boolean embedTypes) {
+        this.customModules = customModules;
+        this.loadCustomSerializers = loadCustomSerializers;
+        this.normalize = normalize;
+        this.embedTypes = embedTypes;
+    }
+
+    @Override
+    public ObjectMapper createMapper() {
+        final ObjectMapper om = new ObjectMapper();
+        om.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+
+        if (embedTypes)
+            om.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, GraphSONTokens.CLASS);
+
+        if (normalize)
+            om.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
+
+        // this provider toStrings all unknown classes and converts keys in Map objects that are Object to String.
+        final DefaultSerializerProvider provider = new GraphSONSerializerProvider();
+        provider.setDefaultKeySerializer(new GraphSONModule.GraphSONKeySerializer());
+        om.setSerializerProvider(provider);
+
+        om.registerModule(new GraphSONModule(normalize));
+        customModules.forEach(om::registerModule);
+
+        // plugin external serialization modules
+        if (loadCustomSerializers)
+            om.findAndRegisterModules();
+
+        // keep streams open to accept multiple values (e.g. multiple vertices)
+        om.getFactory().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+
+        return om;
+    }
+
+    public static Builder build() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private List<SimpleModule> customModules = new ArrayList<>();
+        private boolean loadCustomModules = false;
+        private boolean normalize = false;
+        private boolean embedTypes = false;
+
+        private Builder() {
+        }
+
+        /**
+         * Supply a mapper module for serialization/deserialization.
+         */
+        public Builder addCustomModule(final SimpleModule custom) {
+            this.customModules.add(custom);
+            return this;
+        }
+
+        /**
+         * Try to load {@code SimpleModule} instances from the current classpath.  These are loaded in addition to
+         * the one supplied to the {@link #addCustomModule(com.fasterxml.jackson.databind.module.SimpleModule)};
+         */
+        public Builder loadCustomModules(final boolean loadCustomModules) {
+            this.loadCustomModules = loadCustomModules;
+            return this;
+        }
+
+        /**
+         * Forces keys to be sorted.
+         */
+        public Builder normalize(final boolean normalize) {
+            this.normalize = normalize;
+            return this;
+        }
+
+        /**
+         * Embeds Java types into generated JSON to clarify their origins.
+         */
+        public Builder embedTypes(final boolean embedTypes) {
+            this.embedTypes = embedTypes;
+            return this;
+        }
+
+        public GraphSONMapper create() {
+            return new GraphSONMapper(customModules, loadCustomModules, normalize, embedTypes);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/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
new file mode 100644
index 0000000..6a512b3
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -0,0 +1,299 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.StdKeySerializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.tinkerpop.gremlin.process.Path;
+import com.tinkerpop.gremlin.process.util.metric.Metrics;
+import com.tinkerpop.gremlin.process.util.metric.TraversalMetrics;
+import com.tinkerpop.gremlin.structure.*;
+import com.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
+import com.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONModule extends SimpleModule {
+
+    public GraphSONModule(final boolean normalize) {
+        super("graphson");
+        addSerializer(Edge.class, new EdgeJacksonSerializer());
+        addSerializer(Vertex.class, new VertexJacksonSerializer());
+        addSerializer(GraphSONVertex.class, new GraphSONVertex.VertexJacksonSerializer());
+        addSerializer(GraphSONGraph.class, new GraphSONGraph.GraphJacksonSerializer(normalize));
+        addSerializer(GraphSONVertexProperty.class, new GraphSONVertexProperty.GraphSONVertexPropertySerializer());
+        addSerializer(VertexProperty.class, new VertexPropertyJacksonSerializer());
+        addSerializer(Property.class, new PropertyJacksonSerializer());
+        addSerializer(TraversalMetrics.class, new TraversalMetricsJacksonSerializer());
+        addSerializer(Path.class, new PathJacksonSerializer());
+    }
+
+    static class VertexPropertyJacksonSerializer extends StdSerializer<VertexProperty> {
+        public VertexPropertyJacksonSerializer() {
+            super(VertexProperty.class);
+        }
+
+        @Override
+        public void serialize(final VertexProperty property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(property, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final VertexProperty property, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(property, jsonGenerator);
+        }
+
+        private static void ser(final VertexProperty property, final JsonGenerator jsonGenerator) throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, property.id());
+            m.put(GraphSONTokens.VALUE, property.value());
+            m.put(GraphSONTokens.LABEL, property.label());
+            m.put(GraphSONTokens.PROPERTIES, props(property));
+
+            jsonGenerator.writeObject(m);
+        }
+
+        private static Map<String, Object> props(final VertexProperty property) {
+            if (property instanceof DetachedVertexProperty) {
+                try {
+                    return IteratorUtils.collectMap(property.iterators().propertyIterator(), Property::key, Property::value);
+                } catch (UnsupportedOperationException uoe) {
+                    return new HashMap<>();
+                }
+            } else {
+                return (property.graph().features().vertex().supportsMetaProperties()) ?
+                        IteratorUtils.collectMap(property.iterators().propertyIterator(), Property::key, Property::value) :
+                        new HashMap<>();
+            }
+        }
+    }
+
+    static class PropertyJacksonSerializer extends StdSerializer<Property> {
+        public PropertyJacksonSerializer() {
+            super(Property.class);
+        }
+
+        @Override
+        public void serialize(final Property property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(property, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final Property property, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(property, jsonGenerator);
+        }
+
+        private static void ser(final Property property, final JsonGenerator jsonGenerator) throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.VALUE, property.value());
+            jsonGenerator.writeObject(m);
+        }
+    }
+
+
+    static class EdgeJacksonSerializer extends StdSerializer<Edge> {
+        public EdgeJacksonSerializer() {
+            super(Edge.class);
+        }
+
+        @Override
+        public void serialize(final Edge edge, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(edge, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final Edge edge, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(edge, jsonGenerator);
+        }
+
+        private static void ser(final Edge edge, final JsonGenerator jsonGenerator) throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, edge.id());
+            m.put(GraphSONTokens.LABEL, edge.label());
+            m.put(GraphSONTokens.TYPE, GraphSONTokens.EDGE);
+
+            final Map<String, Object> properties = IteratorUtils.collectMap(edge.iterators().propertyIterator(), Property::key, Property::value);
+            m.put(GraphSONTokens.PROPERTIES, properties);
+
+            final Vertex inV = edge.iterators().vertexIterator(Direction.IN).next();
+            m.put(GraphSONTokens.IN, inV.id());
+            m.put(GraphSONTokens.IN_LABEL, inV.label());
+
+            final Vertex outV = edge.iterators().vertexIterator(Direction.OUT).next();
+            m.put(GraphSONTokens.OUT, outV.id());
+            m.put(GraphSONTokens.OUT_LABEL, outV.label());
+
+            jsonGenerator.writeObject(m);
+        }
+    }
+
+    static class VertexJacksonSerializer extends StdSerializer<Vertex> {
+
+        public VertexJacksonSerializer() {
+            super(Vertex.class);
+        }
+
+        @Override
+        public void serialize(final Vertex vertex, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(vertex, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final Vertex vertex, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(vertex, jsonGenerator);
+
+        }
+
+        private static void ser(final Vertex vertex, final JsonGenerator jsonGenerator)
+                throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, vertex.id());
+            m.put(GraphSONTokens.LABEL, vertex.label());
+            m.put(GraphSONTokens.TYPE, GraphSONTokens.VERTEX);
+
+            // convert to GraphSONVertexProperty so that the label does not get serialized in the output - it is
+            // redundant because the key in the map is the same as the label.
+            final Iterator<GraphSONVertexProperty> vertexPropertyList = IteratorUtils.map(vertex.iterators().propertyIterator(), GraphSONVertexProperty::new);
+            final Object properties = IteratorUtils.groupBy(vertexPropertyList, vp -> vp.getToSerialize().key());
+            m.put(GraphSONTokens.PROPERTIES, properties);
+
+            jsonGenerator.writeObject(m);
+        }
+    }
+
+    static class PathJacksonSerializer extends StdSerializer<Path> {
+        public PathJacksonSerializer() {
+            super(Path.class);
+        }
+
+        @Override
+        public void serialize(final Path path, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException, JsonGenerationException {
+            ser(path, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final Path path, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer)
+                throws IOException, JsonProcessingException {
+            ser(path, jsonGenerator);
+        }
+
+        private static void ser(final Path path, final JsonGenerator jsonGenerator)
+                throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.LABELS, path.labels());
+            m.put(GraphSONTokens.OBJECTS, path.objects());
+            jsonGenerator.writeObject(m);
+        }
+    }
+
+    static class TraversalMetricsJacksonSerializer extends StdSerializer<TraversalMetrics> {
+
+        public TraversalMetricsJacksonSerializer() {
+            super(TraversalMetrics.class);
+        }
+
+        @Override
+        public void serialize(final TraversalMetrics property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            serializeInternal(property, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final TraversalMetrics property, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            serializeInternal(property, jsonGenerator);
+        }
+
+        private static void serializeInternal(final TraversalMetrics traversalMetrics, final JsonGenerator jsonGenerator) throws IOException {
+            final Map<String, Object> m = new HashMap<>();
+
+            m.put(GraphSONTokens.DURATION, traversalMetrics.getDuration(TimeUnit.MILLISECONDS));
+            List<Map<String, Object>> metrics = new ArrayList<>();
+            traversalMetrics.getMetrics().forEach(it -> metrics.add(metricsToMap(it)));
+            m.put(GraphSONTokens.METRICS, metrics);
+
+            jsonGenerator.writeObject(m);
+        }
+
+        private static Map<String, Object> metricsToMap(final Metrics metrics) {
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, metrics.getId());
+            m.put(GraphSONTokens.NAME, metrics.getName());
+            m.put(GraphSONTokens.COUNT, metrics.getCount());
+            m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.MILLISECONDS));
+            m.put(GraphSONTokens.PERCENT_DURATION, metrics.getPercentDuration());
+
+            if (!metrics.getAnnotations().isEmpty()) {
+                m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations());
+            }
+
+            if (!metrics.getNested().isEmpty()) {
+                List<Map<String, Object>> nested = new ArrayList<>();
+                metrics.getNested().forEach(it -> nested.add(metricsToMap(it)));
+                m.put(GraphSONTokens.METRICS, nested);
+            }
+            return m;
+        }
+    }
+
+    /**
+     * Maps in the JVM can have {@link Object} as a key, but in JSON they must be a {@link String}.
+     */
+    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);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/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
new file mode 100644
index 0000000..c5103cf
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
@@ -0,0 +1,265 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.tinkerpop.gremlin.process.T;
+import com.tinkerpop.gremlin.structure.Direction;
+import com.tinkerpop.gremlin.structure.Edge;
+import com.tinkerpop.gremlin.structure.Graph;
+import com.tinkerpop.gremlin.structure.Vertex;
+import com.tinkerpop.gremlin.structure.VertexProperty;
+import com.tinkerpop.gremlin.structure.io.GraphReader;
+import com.tinkerpop.gremlin.structure.util.batch.BatchGraph;
+import com.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import com.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import com.tinkerpop.gremlin.util.function.FunctionUtils;
+import org.javatuples.Pair;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * A @{link GraphReader} that constructs a graph from a JSON-based representation of a graph and its elements.
+ * This implementation only supports JSON data types and is therefore lossy with respect to data types (e.g. a
+ * float will become a double, element IDs may not be retrieved in the format they were serialized, etc.).
+ * {@link Edge} and {@link Vertex} objects are serialized to {@code Map} instances.  If an
+ * {@link com.tinkerpop.gremlin.structure.Element} is used as a key, it is coerced to its identifier.  Other complex
+ * objects are converted via {@link Object#toString()} unless there is a mapper serializer supplied.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONReader implements GraphReader {
+    private final ObjectMapper mapper;
+    private final long batchSize;
+    private final String vertexIdKey;
+    private final String edgeIdKey;
+
+    final TypeReference<Map<String, Object>> mapTypeReference = new TypeReference<Map<String, Object>>() {
+    };
+
+    public GraphSONReader(final GraphSONMapper mapper, final long batchSize,
+                          final String vertexIdKey, final String edgeIdKey) {
+        this.mapper = mapper.createMapper();
+        this.batchSize = batchSize;
+        this.vertexIdKey = vertexIdKey;
+        this.edgeIdKey = edgeIdKey;
+    }
+
+    @Override
+    public void readGraph(final InputStream inputStream, final Graph graphToWriteTo) throws IOException {
+        final BatchGraph graph;
+        try {
+            // will throw an exception if not constructed properly
+            graph = BatchGraph.build(graphToWriteTo)
+                    .vertexIdKey(vertexIdKey)
+                    .edgeIdKey(edgeIdKey)
+                    .bufferSize(batchSize).create();
+        } catch (Exception ex) {
+            throw new IOException("Could not instantiate BatchGraph wrapper", ex);
+        }
+
+        final JsonFactory factory = mapper.getFactory();
+
+        try (JsonParser parser = factory.createParser(inputStream)) {
+            if (parser.nextToken() != JsonToken.START_OBJECT)
+                throw new IOException("Expected data to start with an Object");
+
+            while (parser.nextToken() != JsonToken.END_OBJECT) {
+                final String fieldName = parser.getCurrentName();
+                parser.nextToken();
+
+                if (fieldName.equals(GraphSONTokens.VARIABLES)) {
+                    final Map<String, Object> graphVariables = parser.readValueAs(mapTypeReference);
+                    if (graphToWriteTo.features().graph().variables().supportsVariables())
+                        graphVariables.entrySet().forEach(entry -> graphToWriteTo.variables().set(entry.getKey(), entry.getValue()));
+                } else if (fieldName.equals(GraphSONTokens.VERTICES)) {
+                    while (parser.nextToken() != JsonToken.END_ARRAY) {
+                        final Map<String, Object> vertexData = parser.readValueAs(mapTypeReference);
+                        readVertexData(vertexData, detachedVertex -> {
+                            final Iterator<Vertex> iterator = graph.iterators().vertexIterator(detachedVertex.id());
+                            final Vertex v = iterator.hasNext() ? iterator.next() : graph.addVertex(T.label, detachedVertex.label(), T.id, detachedVertex.id());
+                            detachedVertex.iterators().propertyIterator().forEachRemaining(p -> createVertexProperty(graphToWriteTo, v, p, false));
+                            return v;
+                        });
+                    }
+                } else if (fieldName.equals(GraphSONTokens.EDGES)) {
+                    while (parser.nextToken() != JsonToken.END_ARRAY) {
+                        final Map<String, Object> edgeData = parser.readValueAs(mapTypeReference);
+                        readEdgeData(edgeData, detachedEdge -> {
+                            final Vertex vOut = graph.iterators().vertexIterator(detachedEdge.iterators().vertexIterator(Direction.OUT).next().id()).next();
+                            final Vertex vIn = graph.iterators().vertexIterator(detachedEdge.iterators().vertexIterator(Direction.IN).next().id()).next();
+                            // batchgraph checks for edge id support and uses it if possible.
+                            final Edge e = vOut.addEdge(edgeData.get(GraphSONTokens.LABEL).toString(), vIn, T.id, detachedEdge.id());
+                            detachedEdge.iterators().propertyIterator().forEachRemaining(p -> e.<Object>property(p.key(), p.value()));
+                            return e;
+                        });
+                    }
+                } else
+                    throw new IllegalStateException(String.format("Unexpected token in GraphSON - %s", fieldName));
+            }
+
+            graph.tx().commit();
+        } catch (Exception ex) {
+            throw new IOException(ex);
+        }
+    }
+
+    @Override
+    public Iterator<Vertex> readVertices(final InputStream inputStream, final Direction direction,
+                                         final Function<DetachedVertex, Vertex> vertexMaker,
+                                         final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+        final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
+        return br.lines().<Vertex>map(FunctionUtils.wrapFunction(line -> readVertex(new ByteArrayInputStream(line.getBytes()), direction, vertexMaker, edgeMaker))).iterator();
+    }
+
+    @Override
+    public Edge readEdge(final InputStream inputStream, final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+        final Map<String, Object> edgeData = mapper.readValue(inputStream, mapTypeReference);
+        return readEdgeData(edgeData, edgeMaker);
+    }
+
+    @Override
+    public Vertex readVertex(final InputStream inputStream, final Function<DetachedVertex, Vertex> vertexMaker) throws IOException {
+        final Map<String, Object> vertexData = mapper.readValue(inputStream, mapTypeReference);
+        return readVertexData(vertexData, vertexMaker);
+    }
+
+    @Override
+    public Vertex readVertex(final InputStream inputStream, final Direction direction,
+                             final Function<DetachedVertex, Vertex> vertexMaker,
+                             final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+        final Map<String, Object> vertexData = mapper.readValue(inputStream, mapTypeReference);
+        final Vertex v = readVertexData(vertexData, vertexMaker);
+
+        if (vertexData.containsKey(GraphSONTokens.OUT_E) && (direction == Direction.BOTH || direction == Direction.OUT))
+            readVertexEdges(edgeMaker, vertexData, GraphSONTokens.OUT_E);
+
+        if (vertexData.containsKey(GraphSONTokens.IN_E) && (direction == Direction.BOTH || direction == Direction.IN))
+            readVertexEdges(edgeMaker, vertexData, GraphSONTokens.IN_E);
+
+        return v;
+    }
+
+    private static void createVertexProperty(final Graph graphToWriteTo, final Vertex v, final VertexProperty<Object> p, final boolean hidden) {
+        final List<Object> propertyArgs = new ArrayList<>();
+        if (graphToWriteTo.features().vertex().properties().supportsUserSuppliedIds())
+            propertyArgs.addAll(Arrays.asList(T.id, p.id()));
+        p.iterators().propertyIterator().forEachRemaining(it -> propertyArgs.addAll(Arrays.asList(it.key(), it.value())));
+        v.property(p.key(), p.value(), propertyArgs.toArray());
+    }
+
+    private static void readVertexEdges(final Function<DetachedEdge, Edge> edgeMaker, final Map<String, Object> vertexData, final String direction) throws IOException {
+        final List<Map<String, Object>> edgeDatas = (List<Map<String, Object>>) vertexData.get(direction);
+        for (Map<String, Object> edgeData : edgeDatas) {
+            readEdgeData(edgeData, edgeMaker);
+        }
+    }
+
+    private static Edge readEdgeData(final Map<String, Object> edgeData, final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+        final Map<String, Object> properties = (Map<String, Object>) edgeData.get(GraphSONTokens.PROPERTIES);
+
+        final DetachedEdge edge = new DetachedEdge(edgeData.get(GraphSONTokens.ID),
+                edgeData.get(GraphSONTokens.LABEL).toString(),
+                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()));
+
+        return edgeMaker.apply(edge);
+    }
+
+    private static Vertex readVertexData(final Map<String, Object> vertexData, final Function<DetachedVertex, Vertex> vertexMaker) throws IOException {
+        final Map<String, Object> vertexProperties = (Map<String, Object>) vertexData.get(GraphSONTokens.PROPERTIES);
+        final DetachedVertex vertex = new DetachedVertex(vertexData.get(GraphSONTokens.ID),
+                vertexData.get(GraphSONTokens.LABEL).toString(),
+                vertexProperties);
+
+        return vertexMaker.apply(vertex);
+    }
+
+    public static Builder build() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private long batchSize = BatchGraph.DEFAULT_BUFFER_SIZE;
+        private String vertexIdKey = T.id.getAccessor();
+        private String edgeIdKey = T.id.getAccessor();
+
+        private GraphSONMapper mapper = GraphSONMapper.build().create();
+
+        private Builder() {
+        }
+
+        /**
+         * The name of the key to supply to
+         * {@link com.tinkerpop.gremlin.structure.util.batch.BatchGraph.Builder#vertexIdKey} when reading data into
+         * the {@link Graph}.
+         */
+        public Builder vertexIdKey(final String vertexIdKey) {
+            this.vertexIdKey = vertexIdKey;
+            return this;
+        }
+
+        /**
+         * The name of the key to supply to
+         * {@link com.tinkerpop.gremlin.structure.util.batch.BatchGraph.Builder#edgeIdKey} when reading data into
+         * the {@link Graph}.
+         */
+        public Builder edgeIdKey(final String edgeIdKey) {
+            this.edgeIdKey = edgeIdKey;
+            return this;
+        }
+
+        /**
+         * Number of mutations to perform before a commit is executed.
+         */
+        public Builder batchSize(final long batchSize) {
+            this.batchSize = batchSize;
+            return this;
+        }
+
+        /**
+         * Override all of the {@link GraphSONMapper} builder
+         * options with this mapper.  If this value is set to something other than null then that value will be
+         * used to construct the writer.
+         */
+        public Builder mapper(final GraphSONMapper mapper) {
+            this.mapper = mapper;
+            return this;
+        }
+
+        public GraphSONReader create() {
+            return new GraphSONReader(mapper, batchSize, vertexIdKey, edgeIdKey);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/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
new file mode 100644
index 0000000..089ab63
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializerProvider.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializationConfig;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
+import com.fasterxml.jackson.databind.ser.SerializerFactory;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+
+/**
+ * Implementation of the {@code DefaultSerializerProvider} for Jackson that users the {@code ToStringSerializer} for
+ * unknown types.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class GraphSONSerializerProvider extends DefaultSerializerProvider {
+    private static final long serialVersionUID = 1L;
+    private static final ToStringSerializer toStringSerializer = new ToStringSerializer();
+
+    public GraphSONSerializerProvider() {
+        super();
+    }
+
+    protected GraphSONSerializerProvider(final SerializerProvider src,
+                                         final SerializationConfig config, final SerializerFactory f) {
+        super(src, config, f);
+    }
+
+    @Override
+    public JsonSerializer<Object> getUnknownTypeSerializer(final Class<?> aClass) {
+        return toStringSerializer;
+    }
+
+    @Override
+    public GraphSONSerializerProvider createInstance(final SerializationConfig config,
+                                                     final SerializerFactory jsf) {
+        return new GraphSONSerializerProvider(this, config, jsf);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/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
new file mode 100644
index 0000000..16614b0
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTokens.java
@@ -0,0 +1,51 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class GraphSONTokens {
+    public static final String CLASS = "@class";
+    public static final String ID = "id";
+    public static final String TYPE = "type";
+    public static final String VALUE = "value";
+    public static final String PROPERTIES = "properties";
+    public static final String VARIABLES = "variables";
+    public static final String EDGE = "edge";
+    public static final String EDGES = "edges";
+    public static final String VERTEX = "vertex";
+    public static final String VERTICES = "vertices";
+    public static final String IN = "inV";
+    public static final String OUT = "outV";
+    public static final String IN_E = "inE";
+    public static final String OUT_E = "outE";
+    public static final String LABEL = "label";
+    public static final String LABELS = "labels";
+    public static final String OBJECTS = "objects";
+    public static final String IN_LABEL = "inVLabel";
+    public static final String OUT_LABEL = "outVLabel";
+    // TraversalMetrics Tokens
+    public static final String METRICS = "metrics";
+    public static final String DURATION = "dur";
+    public static final String NAME = "name";
+    public static final String PERCENT_DURATION = "percentDur";
+    public static final String COUNT = "count";
+    public static final String ANNOTATIONS = "annotations";
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertex.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertex.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertex.java
new file mode 100644
index 0000000..12d697a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertex.java
@@ -0,0 +1,94 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.tinkerpop.gremlin.structure.Direction;
+import com.tinkerpop.gremlin.structure.Property;
+import com.tinkerpop.gremlin.structure.Vertex;
+import com.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class GraphSONVertex {
+    private final Direction direction;
+    private final Vertex vertexToSerialize;
+
+    public GraphSONVertex(final Vertex vertexToSerialize, final Direction direction) {
+        this.direction = direction;
+        this.vertexToSerialize = vertexToSerialize;
+    }
+
+    public Direction getDirection() {
+        return direction;
+    }
+
+    public Vertex getVertexToSerialize() {
+        return vertexToSerialize;
+    }
+
+    static class VertexJacksonSerializer extends StdSerializer<GraphSONVertex> {
+
+        public VertexJacksonSerializer() {
+            super(GraphSONVertex.class);
+        }
+
+        @Override
+        public void serialize(final GraphSONVertex directionalVertex, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(directionalVertex, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final GraphSONVertex directionalVertex, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(directionalVertex, jsonGenerator);
+        }
+
+        public static void ser(final GraphSONVertex directionalVertex, final JsonGenerator jsonGenerator) throws IOException {
+            final Vertex vertex = directionalVertex.getVertexToSerialize();
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, vertex.id());
+            m.put(GraphSONTokens.LABEL, vertex.label());
+            m.put(GraphSONTokens.TYPE, GraphSONTokens.VERTEX);
+
+            final Object properties = IteratorUtils.groupBy(vertex.iterators().propertyIterator(), Property::key);
+            m.put(GraphSONTokens.PROPERTIES, properties);
+
+            if (directionalVertex.getDirection() == Direction.BOTH || directionalVertex.getDirection() == Direction.OUT) {
+                m.put(GraphSONTokens.OUT_E, IteratorUtils.fill(vertex.iterators().edgeIterator(Direction.OUT), new ArrayList()));
+            }
+
+            if (directionalVertex.getDirection() == Direction.BOTH || directionalVertex.getDirection() == Direction.IN) {
+                m.put(GraphSONTokens.IN_E, IteratorUtils.fill(vertex.iterators().edgeIterator(Direction.IN), new ArrayList()));
+            }
+
+            jsonGenerator.writeObject(m);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertexProperty.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertexProperty.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertexProperty.java
new file mode 100644
index 0000000..3ee93fe
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONVertexProperty.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.tinkerpop.gremlin.structure.Property;
+import com.tinkerpop.gremlin.structure.VertexProperty;
+import com.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
+import com.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Serializes the {@link VertexProperty} but does so without a label.  This serializer should be used when the
+ * property is serialized as part of a {@link Map} where the label isn't required.  In those cases, the key is
+ * the same as the label and therefore redundant.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONVertexProperty {
+    private final VertexProperty toSerialize;
+
+    public GraphSONVertexProperty(final VertexProperty toSerialize) {
+        this.toSerialize = toSerialize;
+    }
+
+    public VertexProperty getToSerialize() {
+        return toSerialize;
+    }
+
+    static class GraphSONVertexPropertySerializer extends StdSerializer<GraphSONVertexProperty> {
+        public GraphSONVertexPropertySerializer() {
+            super(GraphSONVertexProperty.class);
+        }
+
+        @Override
+        public void serialize(final GraphSONVertexProperty property, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+                throws IOException {
+            ser(property, jsonGenerator);
+        }
+
+        @Override
+        public void serializeWithType(final GraphSONVertexProperty property, final JsonGenerator jsonGenerator,
+                                      final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+            ser(property, jsonGenerator);
+        }
+
+        private static void ser(final GraphSONVertexProperty graphSONVertexProperty, final JsonGenerator jsonGenerator) throws IOException {
+            final VertexProperty property = graphSONVertexProperty.getToSerialize();
+            final Map<String, Object> m = new HashMap<>();
+            m.put(GraphSONTokens.ID, property.id());
+            m.put(GraphSONTokens.VALUE, property.value());
+            m.put(GraphSONTokens.PROPERTIES, props(property));
+
+            jsonGenerator.writeObject(m);
+        }
+
+        private static Map<String, Object> props(final VertexProperty property) {
+            if (property instanceof DetachedVertexProperty) {
+                try {
+                    return IteratorUtils.collectMap(property.iterators().propertyIterator(), Property::key, Property::value);
+                } catch (UnsupportedOperationException uoe) {
+                    return new HashMap<>();
+                }
+            } else {
+                return (property.graph().features().vertex().supportsMetaProperties()) ?
+                        IteratorUtils.collectMap(property.iterators().propertyIterator(), Property::key, Property::value) :
+                        new HashMap<>();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/1545201f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONWriter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONWriter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONWriter.java
new file mode 100644
index 0000000..4b6a2e5
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONWriter.java
@@ -0,0 +1,122 @@
+/*
+ * 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 com.tinkerpop.gremlin.structure.io.graphson;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.tinkerpop.gremlin.process.Traversal;
+import com.tinkerpop.gremlin.structure.Direction;
+import com.tinkerpop.gremlin.structure.Edge;
+import com.tinkerpop.gremlin.structure.Graph;
+import com.tinkerpop.gremlin.structure.Vertex;
+import com.tinkerpop.gremlin.structure.io.GraphWriter;
+
+import java.io.*;
+
+/**
+ * A @{link GraphWriter} that writes a graph and its elements to a JSON-based representation. This implementation
+ * only supports JSON data types and is therefore lossy with respect to data types (e.g. a float will become a double).
+ * Further note that serialized {@code Map} objects do not support complex types for keys.  {@link Edge} and
+ * {@link Vertex} objects are serialized to {@code Map} instances. If an
+ * {@link com.tinkerpop.gremlin.structure.Element} is used as a key, it is coerced to its identifier.  Other complex
+ * objects are converted via {@link Object#toString()} unless a mapper serializer is supplied.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GraphSONWriter implements GraphWriter {
+    private final ObjectMapper mapper;
+
+    private GraphSONWriter(final GraphSONMapper mapper) {
+        this.mapper = mapper.createMapper();
+    }
+
+    @Override
+    public void writeGraph(final OutputStream outputStream, final Graph g) throws IOException {
+        this.mapper.writeValue(outputStream, new GraphSONGraph(g));
+    }
+
+    @Override
+    public void writeVertex(final OutputStream outputStream, final Vertex v, final Direction direction) throws IOException {
+        this.mapper.writeValue(outputStream, new GraphSONVertex(v, direction));
+    }
+
+    @Override
+    public void writeVertex(final OutputStream outputStream, final Vertex v) throws IOException {
+        this.mapper.writeValue(outputStream, v);
+    }
+
+    @Override
+    public void writeEdge(final OutputStream outputStream, final Edge e) throws IOException {
+        this.mapper.writeValue(outputStream, e);
+    }
+
+    @Override
+    public void writeVertices(final OutputStream outputStream, final Traversal<?, Vertex> traversal, final Direction direction) throws IOException {
+        final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+        try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            while (traversal.hasNext()) {
+                writeVertex(baos, traversal.next(), direction);
+                writer.write(new String(baos.toByteArray()));
+                writer.newLine();
+                baos.reset();
+            }
+        }
+
+        writer.flush();
+    }
+
+    @Override
+    public void writeVertices(final OutputStream outputStream, final Traversal<?, Vertex> traversal) throws IOException {
+        final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+        try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            while (traversal.hasNext()) {
+                writeVertex(baos, traversal.next());
+                writer.write(new String(baos.toByteArray()));
+                writer.newLine();
+                baos.reset();
+            }
+        }
+
+        writer.flush();
+    }
+
+    public static Builder build() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private GraphSONMapper mapper = GraphSONMapper.build().create();
+
+        private Builder() {
+        }
+
+        /**
+         * Override all of the builder options with this mapper.  If this value is set to something other than
+         * null then that value will be used to construct the writer.
+         */
+        public Builder mapper(final GraphSONMapper mapper) {
+            this.mapper = mapper;
+            return this;
+        }
+
+        public GraphSONWriter create() {
+            return new GraphSONWriter(mapper);
+        }
+    }
+}