Skip to content

Commit

Permalink
Fix feature serialization when attributes or geometry are null
Browse files Browse the repository at this point in the history
Make feature serialization compliant with RFC 7946 section 3.2. Feature Object:
- A Feature object has a member with the name "geometry".  The value
  of the geometry member SHALL be either a Geometry object as
  defined above or, in the case that the Feature is unlocated, a
  JSON null value.
- A Feature object has a member with the name "properties".  The
  value of the properties member is an object (any JSON object or a
  JSON null value).

https://datatracker.ietf.org/doc/rfc7946/
  • Loading branch information
jjanuszkiewicz committed Aug 3, 2023
1 parent 28502d5 commit 1753b48
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 25 deletions.
15 changes: 4 additions & 11 deletions src/NetTopologySuite.IO.GeoJSON/Converters/FeatureConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Runtime.Serialization;

using NetTopologySuite.Features;
using NetTopologySuite.Geometries;
Expand Down Expand Up @@ -63,18 +62,12 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
}

// geometry
if (serializer.NullValueHandling == NullValueHandling.Include || !(feature.Geometry is null))
{
writer.WritePropertyName("geometry");
serializer.Serialize(writer, feature.Geometry, typeof(Geometry));
}
writer.WritePropertyName("geometry");
serializer.Serialize(writer, feature.Geometry, typeof(Geometry));

// properties
if (serializer.NullValueHandling == NullValueHandling.Include || !(feature.Attributes is null))
{
writer.WritePropertyName("properties");
serializer.Serialize(writer, feature.Attributes, typeof(IAttributesTable));
}
writer.WritePropertyName("properties");
serializer.Serialize(writer, feature.Attributes, typeof(IAttributesTable));

writer.WriteEndObject();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,12 @@ public override void Write(Utf8JsonWriter writer, IFeature value, JsonSerializer
StjGeometryConverter.WriteBBox(writer, value.BoundingBox, options);

// geometry
if (value.Geometry != null || options.ShouldWriteNullValues())
{
writer.WritePropertyName("geometry");
JsonSerializer.Serialize(writer, value.Geometry, options);
}
writer.WritePropertyName("geometry");
JsonSerializer.Serialize(writer, value.Geometry, options);

// properties
if (value.Attributes != null || options.ShouldWriteNullValues())
{
writer.WritePropertyName("properties");
JsonSerializer.Serialize(writer, value.Attributes, options);
}
writer.WritePropertyName("properties");
JsonSerializer.Serialize(writer, value.Attributes, options);

writer.WriteEndObject();
}
Expand Down
22 changes: 20 additions & 2 deletions test/NetTopologySuite.IO.GeoJSON.Test/FeatureConverterTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.IO;
using System.Text;
using NetTopologySuite.Features;
using NetTopologySuite.Geometries;
Expand Down Expand Up @@ -51,6 +50,25 @@ public void WriteJsonTest()
Assert.AreEqual("{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[23.0,56.0]},\"properties\":{\"test1\":\"value1\"}}", sb.ToString());
}

/// <summary>
/// Tests whether required feature members are written, even if they are null.
/// </summary>
[Test]
public void WriteJsonShouldIgnoreCustomNullWritingOptionsTest()
{
var target = new FeatureConverter();
var sb = new StringBuilder();
var writer = new JsonTextWriter(new StringWriter(sb));

IFeature value = new Feature(null, null);
var serializer = GeoJsonSerializer.Create(
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore },
GeometryFactory.Default);
target.WriteJson(writer, value, serializer);
writer.Flush();

Assert.AreEqual("{\"type\":\"Feature\",\"geometry\":null,\"properties\":null}", sb.ToString());
}

///<summary>
/// A test for WriteJson
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ private static void RunTest(Func<JsonSerializerSettings, JsonSerializerSettings,
""type"": ""Feature"",
""geometry"": {
""type"": ""MultiPolygon"",""coordinates"":[[[[0.0,0.0],[0.0,1.0],[1.0,1.0],[1.0,0.0],[0.0,0.0]]]]
}
},
""properties"": null
},
{
""type"": ""Feature"",
""geometry"": {
""type"": ""MultiPolygon"",""coordinates"":[[[[2.0,2.0],[2.0,4.0],[4.0,4.0],[4.0,2.0],[2.0,2.0]]]]
}
},
""properties"": null
}
]
}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ public void WriteJsonTest()
//Assert.AreEqual("{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[23.1,56.2]},\"properties\":{\"test1\":\"value1\"}}", ToJson(value));
}

/// <summary>
/// Tests whether required feature members are written, even if they are null.
/// </summary>
[Test]
public void WriteJsonShouldIgnoreCustomNullWritingOptionsTest()
{
IFeature value = new Feature(null, null);
var options = DefaultOptions;
options.WriteIndented = false;
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;

string json = ToJsonString(value, options);
Assert.AreEqual("{\"type\":\"Feature\",\"geometry\":null,\"properties\":null}", json);
}

///<summary>
/// A test for WriteJson
Expand Down

0 comments on commit 1753b48

Please sign in to comment.