Gremlin.NET deserialize number property

1k Views Asked by At

I have a query that creates a vertex and an edge "Created". The edge has a property "on" which is unix datetime long. When I execute a query with the following segment in the Azure Cosmos DB terminal, it works as expected - an object is returned with an "On" property that is a number.

.project('Id', 'CreatedOn')                    
   .by('id')                    
   .by(
     select('createdEdge')
       .by('on')
    ) 

When I execute this query from my application code using Gremlin.NET, it fails with the error:

JSON type not supported.

I see in the source code that the deserialization logic of Gremlin.NET does not seem to handle any number types. Is this really the case? Is there no way to use long, float, int property types?

2

There are 2 best solutions below

1
On BEST ANSWER

Gremlin.NET does not seem to handle any number types. Is this really the case? Is there no way to use long, float, int property types?

Gremlin.NET does of course support serialization of numerical types. TinkerPop however has its own serialization formats, one of which is the JSON based GraphSON format that is also supported by Cosmos DB. GraphSON basically serializes everything as an object in JSON that consists of a type key and the value. So, an integer will be serialized like this:

{
  "@type" : "g:Int32",
  "@value" : 100
}

This type identifier was added with GraphSON 2 and only used for really all types in GraphSON 3. GraphSON 2 still serialized some types without this type identifier. The GraphSON 2 spec describes this like this:

With GraphSON 2.0, there are essentially two type formats:

  • A non-typed value which is assumed the type implied by JSON. These non-types are limited to String, Boolean, Map and Collection.

  • All other values are typed by way of a "complex object" that defines a @typeId and @value.

As you can see, numerical types are not listed as types that don't have the type identifier.

The Cosmos DB docs mention that they only support GraphSON 2, but it looks like they serialize numerical types without this type identifier. This used to work with Gremlin.NET versions < 3.5.0 as that still had the logic to deserialize numerical types without a type identifier. This was simply a leftover from the GraphSON 1 format which didn't have these type identifiers.

Gremlin.NET 3.5.0 came with major changes to the JSON serialization, mostly due to the switch from Newtonsoft.JSON to System.Text.Json, and this logic was removed as part of that change. So, it looks like you need to stay on Gremlin.NET 3.4 until Cosmos DB fixes their serialization.

1
On

Note there is a work-around as discussed here: https://www.mail-archive.com/[email protected]/msg22532.html

In short, you can create an custom reader derived from GraphSON2Reader:

public class CustomGraphSON2Reader : GraphSON2Reader
{
    public override dynamic ToObject(JsonElement graphSon) =>
        graphSon.ValueKind switch
        {
            // numbers
            JsonValueKind.Number when graphSon.TryGetInt32(out var intValue) => intValue,
            JsonValueKind.Number when graphSon.TryGetInt64(out var longValue) => longValue,
            JsonValueKind.Number when graphSon.TryGetDecimal(out var decimalValue) => decimalValue,
            

            _ => base.ToObject(graphSon)
       };
}

and then pass it into your client:

var client = new GremlinClient(server, new GraphSON2MessageSerializer(new CustomGraphSON2Reader()));