This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch TINKERPOP-3186_dotnet
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 4505a0a74f8824bd6299a424de762f20701562ca
Author: xiazcy <[email protected]>
AuthorDate: Wed Oct 29 21:14:06 2025 -0700

    Normalized Element.properties in .NET to return empty arrays when null
---
 CHANGELOG.asciidoc                                          |  1 +
 docs/src/upgrade/release-3.8.x.asciidoc                     | 13 +++++++------
 gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs         |  4 ++--
 .../Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs   |  2 +-
 .../Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs |  2 +-
 .../Structure/IO/GraphSON/VertexPropertyDeserializer.cs     |  2 +-
 .../Traversal/DriverRemoteConnection/GraphTraversalTests.cs |  8 ++++----
 .../Structure/IO/GraphSON/GraphSONReaderTests.cs            |  5 +++++
 8 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index c01b80c945..171b7f760f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -33,6 +33,7 @@ This release also includes changes from <<release-3-7-XXX, 
3.7.XXX>>.
 * Removed Vertex/ReferenceVertex from grammar. Use vertex id in traversals now 
instead.
 * Removed `has(key, traversal)` and `has(T, traversal)` options for `has()` 
step.
 * Fixed bug where `InlineFilterStrategy` could add an empty `has()`.
+* Normalized dotnet `Element.properties` to lists.
 * Normalized python and javascript `Element.properties` to lists.
 * Renamed `none()` step to `discard()`.
 * Repurposed `none()` step as a list filtering step with the signature 
`none(P)`.
diff --git a/docs/src/upgrade/release-3.8.x.asciidoc 
b/docs/src/upgrade/release-3.8.x.asciidoc
index 9f254b581d..75ce68d0a1 100644
--- a/docs/src/upgrade/release-3.8.x.asciidoc
+++ b/docs/src/upgrade/release-3.8.x.asciidoc
@@ -625,18 +625,19 @@ See: 
link:https://issues.apache.org/jira/browse/TINKERPOP-1463[TINKERPOP-1463]
 
 ==== Serialization Changes
 
-*Properties on Element Serialization in Python & Javascript*
+*Properties on Element Serialization in GLVs*
 
 Element properties handling has been inconsistent across GLVs. 
Previously,`gremlin-python` deserialized empty properties
-as None or array depending on the serializer, while `gremlin-javascript` 
returned properties as objects or arrays, with
-empty properties as empty lists or undefined depending on the serializer.
+as `None` or array depending on the serializer, while `gremlin-javascript`, 
and `gremlin-dotnet` returned properties as
+objects or arrays, with empty properties as empty lists or undefined depending 
on the serializer. (Note that
+`gremlin-go` already returns empty slices for null properties so no changes is 
needed.)
 
 This inconsistency is now resolved, aligning to how properties are handled in 
Gremlin core and in the Java GLV.
-Both GLVs will deserialize element properties into lists of property objects, 
returning empty lists instead of null values
+All GLVs will deserialize element properties into lists of property objects, 
returning empty lists instead of null values
 for missing properties.
 
-For python, the most notable difference is in graphSON when "tokens" is turned 
on for "materializeProperties". The
-properties returned are no longer `None`, but empty lists. Users should update 
their code accordingly.
+For python and dotnet, the most notable difference is in graphSON when 
"tokens" is turned on for "materializeProperties". The
+properties returned are no longer `None` or `null`, but empty lists. Users 
should update their code accordingly.
 
 For javascript, the change is slightly more extensive, as user should no 
longer expect javascript objects to be returned.
 All properties are returned as lists of Property or VertexProperty objects.
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
index 32935bd6d6..bb2cdf4164 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
@@ -41,7 +41,7 @@ namespace Gremlin.Net.Structure
         {
             Id = id;
             Label = label;
-            Properties = properties;
+            Properties = properties ?? Array.Empty<dynamic>();
         }
 
         /// <summary>
@@ -57,7 +57,7 @@ namespace Gremlin.Net.Structure
         /// <summary>
         ///     Gets the properties of this <see cref="Element" />.
         /// </summary>
-        public dynamic[]? Properties { get; }
+        public dynamic[] Properties { get; }
 
         /// <inheritdoc />
         public bool Equals(Element? other)
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
index 4ab5ecdc2d..14a2acda44 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
@@ -45,7 +45,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 ? labelProperty.GetString()!
                 : "edge";
 
-            dynamic[]? properties = null;
+            dynamic[] properties = System.Array.Empty<dynamic>();
             if (graphsonObject.TryGetProperty("properties", out var 
propertiesObject)
                 && propertiesObject.ValueKind == JsonValueKind.Object)
             {
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
index 2412c9a27b..c9c72e09fd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
@@ -36,7 +36,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 ? labelProperty.GetString()!
                 : Vertex.DefaultLabel;
 
-            dynamic[]? properties = null;
+            dynamic[] properties = System.Array.Empty<dynamic>();
             if (graphsonObject.TryGetProperty("properties", out var 
propertiesObject)
                 && propertiesObject.ValueKind == JsonValueKind.Object)
             {
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
index e8e919bee4..0714bc09de 100644
--- 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
+++ 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
@@ -37,7 +37,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 ? new Vertex(reader.ToObject(vertexProperty))
                 : null;
 
-            Property[]? properties = null;
+            Property[] properties = System.Array.Empty<Property>();
             if (graphsonObject.TryGetProperty("properties", out var 
propertiesObject)
                 && propertiesObject.ValueKind == JsonValueKind.Object)
             {
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
index 4f1799450e..6903c04be2 100644
--- 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
@@ -330,7 +330,7 @@ namespace 
Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
             {
                 Assert.NotNull(vp);
                 // GraphSON will deserialize into null and GraphBinary to []
-                Assert.True(vp.Properties == null || vp.Properties.Length == 
0);
+                Assert.True(vp.Properties.Length == 0);
             }
         }
         
@@ -353,9 +353,9 @@ namespace 
Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
             Assert.NotNull(c);
             
             // GraphSON will deserialize into null and GraphBinary to []
-            Assert.True(a.Properties == null || a.Properties.Length == 0);
-            Assert.True(b.Properties == null || b.Properties.Length == 0);
-            Assert.True(c.Properties == null || c.Properties.Length == 0);
+            Assert.True(a.Properties.Length == 0);
+            Assert.True(b.Properties.Length == 0);
+            Assert.True(c.Properties.Length == 0);
         }
         
         [Fact]
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 e903c19b82..a7d314d5be 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
@@ -395,6 +395,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
             Assert.Equal(new Vertex(5L), readPath[0]);
             Assert.Equal(new Vertex(5L), readPath["z"]);
             Assert.Single(readPath);
+            Assert.Empty(readPath[0]!.Properties);
         }
         
         [Theory, MemberData(nameof(Versions))]
@@ -459,6 +460,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
             Assert.Equal("aKey", readVertexProperty.Label);
             Assert.True(readVertexProperty.Value);
             Assert.NotNull(readVertexProperty.Vertex);
+            Assert.Empty(readVertexProperty.Properties);
         }
         
         [Theory, MemberData(nameof(Versions))]
@@ -475,6 +477,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
             Assert.Equal("name", readVertexProperty.Label);
             Assert.Equal("marko", readVertexProperty.Value);
             Assert.Null(readVertexProperty.Vertex);
+            Assert.Empty(readVertexProperty.Properties);
         }
         
         [Theory, MemberData(nameof(Versions))]
@@ -488,6 +491,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
             var deserializedValue = reader.ToObject(jsonElement);
         
             Assert.Equal(new Vertex(45.23f), deserializedValue);
+            Assert.Empty(deserializedValue!.Properties);
         }
         
         [Theory, MemberData(nameof(Versions))]
@@ -501,6 +505,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
             Vertex deserializedValue = reader.ToObject(jsonElement)!;
         
             Assert.Equal("person", deserializedValue.Label);
+            Assert.Empty(deserializedValue.Properties);
         }
         
         [Theory, MemberData(nameof(Versions))]

Reply via email to