Fredy created TINKERPOP-2581:
--------------------------------
Summary: Gremlin.NET throwing an exception when having to
deserialize Numbers in edges
Key: TINKERPOP-2581
URL: https://issues.apache.org/jira/browse/TINKERPOP-2581
Project: TinkerPop
Issue Type: Bug
Components: dotnet
Affects Versions: 3.5.0
Environment: Azure CosmosDB graph
Reporter: Fredy
We use Gremlin.NET against a CosmosDB graph and have upgraded our projects from
3.4.10 to 3.5.0 which I understand changed serialization to use
System.Text.Json.
We discovered that many of our queries that ended up retrieving edges were
failing with the following ArgumentOutOfRangeException exception:
{code:java}
JSON type not supported.Parameter name: ValueKindActual value was Number.
{code}
We determined this happens for queries retrieving edges that have Number type
JSON properties, most likely because Number is not considered in the ToObject
method:
[https://github.com/apache/tinkerpop/blob/a7181e23421818948de3624743d79361524c0013/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs#L103]
A workaround that seems to work is instantiate our Gremlin.NET client with a
subclass of GraphSON2Reader that accounts for this, but for the time being
we've decided to rollback the update instead.
Here's some code that triggers the issue, at least when using the CosmosDB
backend which is what we use:
{code:java}
using Gremlin.Net.Driver;
using Gremlin.Net.Structure.IO.GraphSON;
using System;
using System.Text.Json;
using System.Threading.Tasks;namespace GremlinNetTest
{
class Program
{
static async Task Main(string[] _)
{
var (hostname, port, username, password) = (
"<redacted>",
443,
"<redacted>",
"<redacted>"
);
var server = new GremlinServer(hostname, port, enableSsl: true,
username, password);
var client = new GremlinClient(server, new
GraphSON2MessageSerializer(new GraphSON2Reader(), new GraphSON2Writer()));
// Create vertexes.
var (v1Id, v2Id) = (Guid.NewGuid().ToString(),
Guid.NewGuid().ToString());
await
client.SubmitAsync<dynamic>($"g.addV('item').property('id','{v1Id}').property('pk','0')");
await
client.SubmitAsync<dynamic>($"g.addV('item').property('id','{v2Id}').property('pk','0')");
// Create edge with string property works.
await
client.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('works').to(g.V(['0','{v2Id}'])).property('hello','world')");
// Create edge with number property fails to deserialize result.
// ** FAILS **
await
client.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('fails').to(g.V(['0','{v2Id}'])).property('number',
1)");
await
client.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('fails').to(g.V(['0','{v2Id}'])).property('long',
3147483647)");
await
client.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('fails').to(g.V(['0','{v2Id}'])).property('decimal',
1.5)");
// ** /FAILS ** // Create edge with number property
works to deserialize result with custom reader.
var clientWithCustomReader = new GremlinClient(server, new
GraphSON2MessageSerializer(new CustomReader(), new GraphSON2Writer()));
await
clientWithCustomReader.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('works').to(g.V(['0','{v2Id}'])).property('number',
1)");
await
clientWithCustomReader.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('works').to(g.V(['0','{v2Id}'])).property('long',
3147483647)");
await
clientWithCustomReader.SubmitAsync<dynamic>($"g.V(['0','{v1Id}']).addE('works').to(g.V(['0','{v2Id}'])).property('decimal',
1.5)");
}
} public class CustomReader : GraphSON2Reader
{
public override dynamic ToObject(JsonElement graphSon)
{
if (graphSon.ValueKind == JsonValueKind.Number)
{
if (graphSon.TryGetInt32(out int intValue)) return intValue;
if (graphSon.TryGetInt64(out long longValue)) return longValue;
if (graphSon.TryGetDecimal(out decimal decimalValue)) return
decimalValue;
}
return base.ToObject(graphSon);
}
}
}
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)