GraphBinary is a binary serialization format suitable for object trees, designed to reduce serialization overhead on both the client and the server, as well as limiting the size of the payload that is transmitted over the wire.
It describes arbitrary object graphs with a fully-qualified format:
{type_code}{type_info}{value_flag}{value}
Where:
-
{type_code}
is a single unsigned byte representing the type number. -
{type_info}
is an optional sequence of bytes providing additional information of the type represented. This is specially useful for representing complex and custom types. -
{value_flag}
is a single byte providing information about the value. Each type may have its own specific flags so see each type for more details. Generally, flags have the following meaning:-
0x01
The value isnull
. When this flag is set, no bytes for{value}
will be provided.
-
-
{value}
is a sequence of bytes which content is determined by the type.
All encodings are big-endian.
Quick examples, using hexadecimal notation to represent each byte:
-
01 00 00 00 00 01
: a 32-bit integer number, that represents the decimal number 1. It’s composed by the type_code0x01
, and empty flag value0x00
and four bytes to describe the value. -
01 00 00 00 00 ff
: a 32-bit integer, representing the number 256. -
01 01
: a null value for a 32-bit integer. It’s composed by the type_code0x01
, and a null flag value0x01
. -
02 00 00 00 00 00 00 00 00 01
: a 64-bit integer number 1. It’s composed by the type_code0x02
, empty flags and eight bytes to describe the value.
The serialization format supports new types being added without the need to introduce a new version.
Changes to existing types require new revision.
-
0x01
: Int -
0x02
: Long -
0x03
: String -
0x04
: DateTime -
0x07
: Double -
0x08
: Float -
0x09
: List -
0x0a
: Map -
0x0b
: Set -
0x0c
: UUID -
0x0d
: Edge -
0x0e
: Path -
0x0f
: Property -
0x10
: TinkerGraph -
0x11
: Vertex -
0x12
: VertexProperty -
0x18
: Direction -
0x20
: T -
0x22
: BigDecimal -
0x23
: BigInteger -
0x24
: Byte -
0x25
: Binary -
0x26
: Short -
0x27
: Boolean -
0x2b
: Tree -
0xf0
: CompositePDT -
0xf1
: PrimitivePDT -
0xfd
: Marker -
0xfe
: Unspecified null object
The serialization format defines two ways to represent null values:
-
Unspecified null object
-
Fully-qualified null
When a parent type can contain any subtype e.g., a object collection, a null
value must be represented using the
"Unspecified Null Object" type code and the null value flag.
In contrast, when the parent type contains a type parameter that must be specified, a null
value is represented using
a fully-qualified object using the appropriate type code and type information.
Format: 4-byte two’s complement integer.
Example values:
-
00 00 00 01
: 32-bit integer number 1. -
00 00 01 01
: 32-bit integer number 256. -
ff ff ff ff
: 32-bit integer number -1. -
ff ff ff fe
: 32-bit integer number -2.
Format: 8-byte two’s complement integer.
Example values
-
00 00 00 00 00 00 00 01
: 64-bit integer number 1. -
ff ff ff ff ff ff ff fe
: 64-bit integer number -2.
Format: {length}{text_value}
Where:
-
{length}
is anInt
describing the byte length of the text. Length is a positive number or zero to represent the empty string. -
{text_value}
is a sequence of bytes representing the string value in UTF8 encoding.
Example values
-
00 00 00 03 61 62 63
: the string 'abc'. -
00 00 00 04 61 62 63 64
: the string 'abcd'. -
00 00 00 00
: the empty string ''.
A date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00.
Format: {year}{month}{day}{time}{offset}
Where:
-
{year}
is anInt
from -999,999,999 to 999,999,999. -
{month}
is aByte
to represent the month, from 1 (January) to 12 (December) -
{day}
is aByte
from 1 to 31. -
{time}
is aLong
to represent nanoseconds since midnight, from 0 to 86399999999999 -
{offset}
is anInt
to represent total zone offset in seconds, from -64800 (-18:00) to 64800 (+18:00).
Format: 8 bytes representing IEEE 754 double-precision binary floating-point format.
Example values
-
3f f0 00 00 00 00 00 00
: Double 1 -
3f 70 00 00 00 00 00 00
: Double 0.00390625 -
3f b9 99 99 99 99 99 9a
: Double 0.1
Format: 4 bytes representing IEEE 754 single-precision binary floating-point format.
Example values
-
3f 80 00 00
: Float 1 -
3e c0 00 00
: Float 0.375
An ordered collection of items. The format depends on the {value_flag}.
Format (value_flag=0x00): {length}{item_0}…{item_n}
Where:
-
{length}
is anInt
describing the length of the collection. -
{item_0}…{item_n}
are the items of the list.{item_i}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
.
Format (value_flag=0x02): {length}{item_0}{bulk_0}…{item_n}{bulk_n}
Where:
-
{length}
is anInt
describing the length of the collection. -
{item_0}…{item_n}
are the items of the list.{item_i}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{bulk_0}…{bulk_n}
areInt
that represent how many times that item should be repeated in the expanded list.
A dictionary of keys to values. A {value_flag} equal to 0x02 means that the map is ordered.
Format: {length}{item_0}…{item_n}
Where:
-
{length}
is anInt
describing the length of the map. -
{item_0}…{item_n}
are the items of the map.{item_i}
is sequence of 2 fully qualified typed values one representing the key and the following representing the value, each composed of{type_code}{type_info}{value_flag}{value}
.
A 128-bit universally unique identifier.
Format: 16 bytes representing the uuid.
Example
-
00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
: Uuid 00112233-4455-6677-8899-aabbccddeeff.
Format: {id}{label}{inVId}{inVLabel}{outVId}{outVLabel}{parent}{properties}
Where:
-
{id}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{label}
is aList
{value}. -
{inVId}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{inVLabel}
is aList
{value}. -
{outVId}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{outVLabel}
is aList
{value}. -
{parent}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
which contains the parentVertex
. Note that as TinkerPop currently send "references" only, this value will always benull
. -
{properties}
is aList
ofProperty
objects.
Example values:
01 00 00 00 00 0d id is 13
00 00 00 01 03 00 00 00 00 08 64 65 76 65 6c 6f 70 73 label is a size 1 list with string 'develops'
01 00 00 00 00 0a inVId is 10
00 00 00 01 03 00 00 00 00 08 73 6f 66 74 77 61 72 65 inVLabel is a size 1 list with string 'software'
01 00 00 00 00 01 outVId is 1
00 00 00 01 03 00 00 00 00 06 70 65 72 73 6f 6e outVLabel is a size 1 list with string 'person'
fe 01 parent is always null
09 00 00 00 00 01 properties is a size 1 list
0f 00 00 00 00 05 73 69 6e 63 65 01 00 00 00 07 d9 fe 01 property with key 'since' and value 2009 and null parent
Format: {labels}{objects}
Where:
-
{labels}
is a fully qualifiedList
in which each item is a fully qualifiedSet
ofString
. -
{objects}
is a fully qualifiedList
of fully qualified typed values.
Format: {key}{value}{parent}
Where:
-
{key}
is aString
value. -
{value}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{parent}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
which is either anEdge
orVertexProperty
. Note that as TinkerPop currently sends "references" only this value will always benull
.
A collection of vertices and edges. Note that while similar the vertex/edge formats here hold some differences as
compared to the Vertex
and Edge
formats used for standard serialization/deserialiation of a single graph element.
Format: {vlength}{vertex_0}…{vertex_n}{elength}{edge_0}…{edge_n}
Where:
-
{vlength}
is anInt
describing the number of vertices. -
{vertex_0}…{vertex_n}
are vertices as described below. -
{elength}
is anInt
describing the number of edges. -
{edge_0}…{edge_n}
are edges as described below.
Vertex Format: {id}{label}{plength}{property_0}…{property_n}
-
{id}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{label}
is aString
value. -
{plength}
is anInt
describing the number of properties on the vertex. -
{property_0}…{property_n}
are the vertex properties consisting of{id}{label}{value}{parent}{properties}
as defined inVertexProperty
where the{parent}
is alwaysnull
and{properties}
is aList
ofProperty
objects.
Edge Format: {id}{label}{inVId}{inVLabel}{outVId}{outVLabel}{parent}{properties}
Where:
-
{id}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{label}
is aString
value. -
{inVId}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{inVLabel}
is alwaysnull
. -
{outVId}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{outVLabel}
is alwaysnull
. -
{parent}
is alwaysnull
. -
{properties}
is aList
ofProperty
objects.
Format: {id}{label}{properties}
Where:
-
{id}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{label}
is aList
{value}. -
{properties}
is aList
ofVertexProperty
values.
Example values:
01 00 00 00 00 01 id is int 1
00 00 00 01 03 00 00 00 00 06 70 65 72 73 6f 6e label is size 1 list with string 'person'
09 00 00 00 00 01 12 00 02 00 00 00 00 00 00 00 00 09 properties is a size 1 list with VertexProperty id 9
00 00 00 01 03 00 00 00 00 08 6c 6f 63 61 74 69 6f 6e VertexProperty label is string 'location'
03 00 00 00 00 08 73 61 6e 74 61 20 66 65 VertexProperty value is string 'santa fe'
fe 01 VertexProperty parent is always null
09 00 00 00 00 01 VertexProperty has a size 1 list
0f 00 00 00 00 09 73 74 61 72 74 54 69 6d 65 metaproperty with string key 'startTime'
01 00 00 00 07 d5 fe 01 VertexProperty metaproperty value is 2005 with null parent
Format: {id}{label}{value}{parent}{properties}
Where:
-
{id}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{label}
is aList
{value}. -
{value}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. -
{parent}
is a fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
which contains the parentVertex
. Note that as TinkerPop currently send "references" only, this value will always benull
. -
{properties}
is aList
ofProperty
objects.
Example values:
02 00 00 00 00 00 00 00 00 00 id is Long 0
00 00 00 01 03 00 00 00 00 04 6e 61 6d 65 label is size 1 list with string 'name'
03 00 00 00 00 05 6d 61 72 6b 6f value is string 'marko'
fe 01 parent is always null
09 00 00 00 00 00 metaproperties is empty list
Format: a fully qualified single String
representing the enum value.
Example values:
-
00 00 00 03 4F 55 54
: OUT -
00 00 00 02 49 4E
: IN
Format: a fully qualified single String
representing the enum value.
Example values:
-
00 00 00 05 6C 61 62 65 6C
: label -
00 00 00 02 69 64
: id
Represents an arbitrary-precision signed decimal number, consisting of an arbitrary precision integer unscaled value and a 32-bit integer scale.
Format: {scale}{unscaled_value}
Where:
-
{scale}
is anInt
. -
{unscaled_value}
is aBigInteger
.
A variable-length two’s complement encoding of a signed integer.
Format: {length}{value}
Where:
-
{length}
is anInt
describing the size of{value}
in bytes. -
{value}
is the two’s complement of theBigInteger
.
Example values of the two’s complement {value}
:
-
00
: Integer 0. -
01
: Integer 1. -
127
: Integer 7f. -
00 80
: Integer 128. -
ff
: Integer -1. -
80
: Integer -128. -
ff 7f
: Integer -129.
Format: 1-byte two’s complement integer.
Example values:
-
01
: 8-bit integer number 1. -
ff
: 8-bit integer number -1.
Format: {length}{value}
Where:
-
{length}
is anInt
representing the amount of bytes contained in the value. -
{value}
sequence of bytes.
Format: 2-byte two’s complement integer.
Example values:
-
00 01
: 16-bit integer number 1. -
01 02
: 16-bit integer number 258.
Format: {length}{item_0}…{item_n}
Where:
-
{length}
is anInt
describing the amount of items. -
{item_0}…{item_n}
are the items of theTree
.{item_i}
is composed of a{key}
which is a fully-qualified typed value followed by a{Tree}
.
A 1-byte marker used to separate the end of the data and the beginning of the status of a ResponseMessage
. This is
mainly used by language variants during deserialization.
Format: 1-byte integer with a value of 00
.
A composite custom type, represented as a type and a map of values.
Format: {type}{fields}
Where:
-
{type}
is aString
containing the implementation specific text identifier of the custom type. -
{fields}
is aMap
representing the fields of the composite type.
Example values:
03 00 00 00 00 05 50 6F 69 6E 74: the string "Point"
0A 00 00 00 00 02 31 30: length 2 map header
03 00 00 00 00 01 78 01 00 00 00 00 01: {x:1}
03 00 00 00 00 01 79 01 00 00 00 00 02: {y:2}
A primitive custom type, represented as a type and the stringified value.
Format: {type}{value}
Where:
-
{type}
is aString
containing the implementation specific text identifier of the custom type. -
{value}
is aString
representing the string version of the value.
Example values:
03 00 00 00 00 05 55 69 6E 74 38: the string "Uint8"
03 00 00 00 00 02 31 30: the string "10"
A null
value for an unspecified Object value.
It’s represented using the null {value_flag}
set and no sequence of bytes (which is FE 01
).
Format: one to four bytes representing a single UTF8 char, according to the Unicode standard.
For characters 0x00
-0x7F
, UTF-8 encodes the character as a single byte.
For characters 0x80
-0x07FF
, UTF-8 uses 2 bytes: the first byte is binary 110
followed by the 5 high bits of the
character, while the second byte is binary 10 followed by the 6 low bits of the character.
The 3 and 4-byte encodings are similar to the 2-byte encoding, except that the first byte of the 3-byte encoding starts
with 1110
and the first byte of the 4-byte encoding starts with 11110
.
Example values (hex bytes)
-
97
: Character 'a'. -
c2 a2
: Character '¢'. -
e2 82 ac
: Character '€'
Request and response messages are special container types used to represent messages from client to the server and the other way around. These messages are independent from the transport layer.
Represents a message from the client to the server.
Format: {version}{fields}{gremlin}
Where:
-
{version}
is aByte
representing the specification version, with the most significant bit set to one. For this version of the format, the value expected is0x84
(10000004
). -
{fields}
is aMap
. -
{gremlin}
is aString
.
The total length is not part of the message as the transport layer will provide it. For example: in HTTP, there is the
Content-Length
header which defines the payload size.
Format: {version}{bulked}{result_data}{marker}{status_code}{status_message}{exception}
Where:
-
{version}
is aByte
representing the protocol version, with the most significant bit set to one. For this version of the protocol, the value expected is0x84
(10000004
). -
{bulked}
is aByte
representing whether{result_data}
is bulked.00
is false and01
is true. -
{result_data}
is a sequence of fully qualified typed value composed of{type_code}{type_info}{value_flag}{value}
. If{bulked}
is01
then each value is followed by an 8-byte integer denoting the bulk of the preceding value. -
{marker}
is aMarker
. -
{status_code}
is anInt
. -
{status_message}
is a nullableString
. -
{exception}
is a nullableString
.
The total length is not part of the message as the transport layer will provide it.