TINKERPOP-2055 Support NaN/Infinity on 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/5b9b81fd Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5b9b81fd Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5b9b81fd Branch: refs/heads/tp33 Commit: 5b9b81fdea9778f777a01aa2a70bc93510f16399 Parents: 28bf304 Author: Stephen Mallette <sp...@genoprime.com> Authored: Thu Oct 4 14:53:04 2018 -0400 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Thu Oct 4 14:53:04 2018 -0400 ---------------------------------------------------------------------- .../structure/io/graphson/GraphSONModule.java | 2 +- .../io/graphson/GraphSONSerializersV3d0.java | 23 ++++++++++++----- .../IO/GraphSON/GraphSONReaderTests.cs | 7 +++--- .../IO/GraphSON/GraphSONWriterTests.cs | 2 +- .../gremlin_python/structure/io/graphsonV3d0.py | 26 ++++++++++++++++++++ .../tests/structure/io/test_graphsonV3d0.py | 22 +++++++++++++++++ 6 files changed, 71 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5b9b81fd/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 2e795a5..39f1927 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 @@ -254,7 +254,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule { // numbers addDeserializer(Integer.class, new GraphSONSerializersV3d0.IntegerJackonsDeserializer()); - addDeserializer(Double.class, new GraphSONSerializersV3d0.DoubleJackonsDeserializer()); + addDeserializer(Double.class, new GraphSONSerializersV3d0.DoubleJacksonDeserializer()); // traversal addDeserializer(Bytecode.class, new TraversalSerializersV3d0.BytecodeJacksonDeserializer()); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5b9b81fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java index 8c601b1..8d80478 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV3d0.java @@ -47,11 +47,9 @@ import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException; import org.apache.tinkerpop.shaded.jackson.core.JsonToken; import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext; import org.apache.tinkerpop.shaded.jackson.databind.JavaType; -import org.apache.tinkerpop.shaded.jackson.databind.JsonNode; import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider; import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer; import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer; -import org.apache.tinkerpop.shaded.jackson.databind.node.ArrayNode; import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdKeySerializer; import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer; import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer; @@ -705,15 +703,28 @@ class GraphSONSerializersV3d0 { } } - static class DoubleJackonsDeserializer extends StdDeserializer<Double> { + static class DoubleJacksonDeserializer extends StdDeserializer<Double> { - protected DoubleJackonsDeserializer() { + protected DoubleJacksonDeserializer() { super(Double.class); } @Override - public Double deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { - return jsonParser.getDoubleValue(); + public Double deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + if (jsonParser.getCurrentToken().isNumeric()) + return jsonParser.getDoubleValue(); + else { + final String numberText = jsonParser.getValueAsString(); + if ("NaN".equalsIgnoreCase(numberText)) + return Double.NaN; + else if ("-Infinity".equals(numberText) || "-INF".equalsIgnoreCase(numberText)) + return Double.NEGATIVE_INFINITY; + else if ("Infinity".equals(numberText) || "INF".equals(numberText)) + return Double.POSITIVE_INFINITY; + else + throw new IllegalStateException("Double value unexpected: " + numberText); + } + } @Override http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5b9b81fd/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs index 15e5b05..af48f02 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs @@ -24,6 +24,7 @@ using System; using System.Collections.Generic; using System.Numerics; +using Gremlin.Net.Process.Traversal; using Gremlin.Net.Structure; using Gremlin.Net.Structure.IO.GraphSON; using Moq; @@ -200,7 +201,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON public void ShouldDeserializeNaN(int version) { var serializedValue = "{\"@type\":\"g:Double\",\"@value\":'NaN'}"; - var reader = CreateStandardGraphSONReader(); + var reader = CreateStandardGraphSONReader(version); var jObject = JObject.Parse(serializedValue); var deserializedValue = reader.ToObject(jObject); @@ -212,7 +213,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON public void ShouldDeserializePositiveInfinity(int version) { var serializedValue = "{\"@type\":\"g:Double\",\"@value\":'Infinity'}"; - var reader = CreateStandardGraphSONReader(); + var reader = CreateStandardGraphSONReader(version); var jObject = JObject.Parse(serializedValue); var deserializedValue = reader.ToObject(jObject); @@ -224,7 +225,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON public void ShouldDeserializeNegativeInfinity(int version) { var serializedValue = "{\"@type\":\"g:Double\",\"@value\":'-Infinity'}"; - var reader = CreateStandardGraphSONReader(); + var reader = CreateStandardGraphSONReader(version); var jObject = JObject.Parse(serializedValue); var deserializedValue = reader.ToObject(jObject); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5b9b81fd/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs index 07f00a9..c8ec43a 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs @@ -124,7 +124,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON [Theory, MemberData(nameof(Versions))] public void ShouldSerializeNegativeInfinity(int version) { - var writer = CreateGraphSONWriter(); + var writer = CreateGraphSONWriter(version); var graphSon = writer.WriteObject(Double.NegativeInfinity); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5b9b81fd/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py index 5539448..a041421 100644 --- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py +++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py @@ -20,6 +20,7 @@ import datetime import json import time import uuid +import math from collections import OrderedDict import six @@ -464,6 +465,31 @@ class FloatIO(_NumberIO): graphson_type = "g:Float" graphson_base_type = "Float" + @classmethod + def dictify(cls, n, writer): + if isinstance(n, bool): # because isinstance(False, int) and isinstance(True, int) + return n + elif math.isnan(n): + return GraphSONUtil.typedValue(cls.graphson_base_type, "NaN") + elif math.isinf(n) and n > 0: + return GraphSONUtil.typedValue(cls.graphson_base_type, "Infinity") + elif math.isinf(n) and n < 0: + return GraphSONUtil.typedValue(cls.graphson_base_type, "-Infinity") + else: + return GraphSONUtil.typedValue(cls.graphson_base_type, n) + + @classmethod + def objectify(cls, v, _): + if isinstance(v, str): + if v == 'NaN': + return float('nan') + elif v == "Infinity": + return float('inf') + elif v == "-Infinity": + return float('-inf') + + return cls.python_type(v) + class DoubleIO(FloatIO): graphson_type = "g:Double" http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5b9b81fd/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py b/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py index 16de67f..4aa4eed 100644 --- a/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py +++ b/gremlin-python/src/main/jython/tests/structure/io/test_graphsonV3d0.py @@ -23,6 +23,7 @@ import datetime import time import json import uuid +import math from mock import Mock @@ -96,6 +97,27 @@ class TestGraphSONReader(object): })) assert isinstance(x, float) assert 31.2 == x + ## + x = self.graphson_reader.readObject(json.dumps({ + "@type": "g:Double", + "@value": "NaN" + })) + assert isinstance(x, float) + assert math.isnan(x) + ## + x = self.graphson_reader.readObject(json.dumps({ + "@type": "g:Double", + "@value": "Infinity" + })) + assert isinstance(x, float) + assert math.isinf(x) and x > 0 + ## + x = self.graphson_reader.readObject(json.dumps({ + "@type": "g:Double", + "@value": "-Infinity" + })) + assert isinstance(x, float) + assert math.isinf(x) and x < 0 def test_graph(self): vertex = self.graphson_reader.readObject("""