Skip to content

Commit 0ec813b

Browse files
committed
Handle null altitudes when reading positions
1 parent 44366de commit 0ec813b

File tree

4 files changed

+114
-9
lines changed

4 files changed

+114
-9
lines changed

src/GeoJSON.Text.Test.Unit/GeoJSON.Text.Test.Unit.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<None Remove="Feature\GenericFeatureTests_Can_Deserialize_Typed_Point_Feature.json" />
2323
<None Remove="Feature\GenericFeatureTests_Can_Serialize_Typed_Point_Feature.json" />
2424
<None Remove="Geometry\LineStringTests_Can_Deserialize.json" />
25+
<None Remove="Geometry\LineStringTests_Can_Deserialize_With_Altitude.json" />
2526
<None Remove="Geometry\LineStringTests_Can_Serialize.json" />
2627
<None Remove="Geometry\MultiLineStringTests_Can_Deserialize.json" />
2728
<None Remove="Geometry\MultiLineStringTests_Can_Serialize.json" />
@@ -76,6 +77,9 @@
7677
<ItemGroup>
7778
<ProjectReference Include="..\GeoJSON.Text\GeoJSON.Text.csproj" />
7879
</ItemGroup>
80+
<ItemGroup>
81+
<EmbeddedResource Include="Geometry\LineStringTests_Can_Deserialize_With_Altitude.json" />
82+
</ItemGroup>
7983
<ItemGroup>
8084
<None Update="Feature\*.json">
8185
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

src/GeoJSON.Text.Test.Unit/Geometry/LineStringTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,31 @@ public void Can_Deserialize()
8383
Assert.AreEqual(expectedLineString.Coordinates[0].Longitude, actualLineString.Coordinates[0].Longitude);
8484
}
8585

86+
[Test]
87+
public void Can_Deserialize_With_Altitude()
88+
{
89+
var coordinates = new List<IPosition>
90+
{
91+
new Position(52.370725881211314, 4.889259338378906, 10.0),
92+
new Position(52.3711451105601, 4.895267486572266, 10.5),
93+
new Position(52.36931095278263, 4.892091751098633, null),
94+
new Position(52.370725881211314, 4.889259338378906, 10.2)
95+
};
96+
97+
var expectedLineString = new LineString(coordinates);
98+
99+
var json = GetExpectedJson();
100+
var actualLineString = JsonSerializer.Deserialize<LineString>(json);
101+
102+
Assert.AreEqual(expectedLineString, actualLineString);
103+
104+
Assert.AreEqual(4, actualLineString.Coordinates.Count);
105+
Assert.AreEqual(expectedLineString.Coordinates[0].Latitude, actualLineString.Coordinates[0].Latitude);
106+
Assert.AreEqual(expectedLineString.Coordinates[0].Longitude, actualLineString.Coordinates[0].Longitude);
107+
Assert.AreEqual(expectedLineString.Coordinates[0].Altitude, actualLineString.Coordinates[0].Altitude);
108+
Assert.AreEqual(expectedLineString.Coordinates[2].Altitude, actualLineString.Coordinates[2].Altitude);
109+
}
110+
86111
[Test]
87112
public void Constructor_No_Coordinates_Throws_Exception()
88113
{
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"coordinates": [
3+
[4.8892593383789062, 52.370725881211314, 10.0],
4+
[4.8952674865722656, 52.3711451105601, 10.5],
5+
[4.8920917510986328, 52.369310952782627, null],
6+
[4.8892593383789062, 52.370725881211314, 10.2]
7+
],
8+
"type": "LineString"
9+
}

src/GeoJSON.Text/Converters/PositionConverter.cs

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using GeoJSON.Text.Geometry;
44
using System;
5+
using System.Collections.Generic;
56
using System.Text.Json;
67
using System.Text.Json.Serialization;
78

@@ -28,10 +29,9 @@ public override bool CanConvert(Type objectType)
2829
/// <summary>
2930
/// Reads the JSON representation of the object.
3031
/// </summary>
31-
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param>
32-
/// <param name="objectType">Type of the object.</param>
33-
/// <param name="existingValue">The existing value of object being read.</param>
34-
/// <param name="serializer">The calling serializer.</param>
32+
/// <param name="reader">The <see cref="T:System.Text.Json.Utf8JsonReader" /> to read from.</param>
33+
/// <param name="type">Type of the object.</param>
34+
/// <param name="options">Serializer options.</param>
3535
/// <returns>
3636
/// The object value.
3737
/// </returns>
@@ -40,17 +40,84 @@ public override IPosition Read(
4040
Type type,
4141
JsonSerializerOptions options)
4242
{
43-
double[] coordinates;
44-
4543
try
46-
{
47-
coordinates = JsonSerializer.Deserialize<double[]>(ref reader, options);
44+
{
45+
if (reader.TokenType != JsonTokenType.StartArray)
46+
{
47+
throw new ArgumentException("Expected start of array");
48+
}
49+
50+
double lng, lat;
51+
double? alt;
52+
53+
// Read longitude
54+
if (!reader.Read())
55+
{
56+
throw new ArgumentException("Expected number, but got end of data");
57+
}
58+
if (reader.TokenType == JsonTokenType.EndArray)
59+
{
60+
throw new ArgumentException("Expected 2 or 3 coordinates but got 0");
61+
}
62+
if (reader.TokenType != JsonTokenType.Number)
63+
{
64+
throw new ArgumentException("Expected number but got other type");
65+
}
66+
lng = reader.GetDouble();
67+
68+
// Read latitude
69+
if (!reader.Read())
70+
{
71+
throw new ArgumentException("Expected number, but got end of data");
72+
}
73+
if (reader.TokenType == JsonTokenType.EndArray)
74+
{
75+
throw new ArgumentException("Expected 2 or 3 coordinates but got 1");
76+
}
77+
if (reader.TokenType != JsonTokenType.Number)
78+
{
79+
throw new ArgumentException("Expected number but got other type");
80+
}
81+
lat = reader.GetDouble();
82+
83+
// Read altitude, or return if end of array is found
84+
if (!reader.Read())
85+
{
86+
throw new ArgumentException("Unexpected end of data");
87+
}
88+
if (reader.TokenType == JsonTokenType.EndArray)
89+
{
90+
return new Position(lat, lng);
91+
}
92+
else if (reader.TokenType == JsonTokenType.Null)
93+
{
94+
alt = null;
95+
}
96+
else if (reader.TokenType == JsonTokenType.Number)
97+
{
98+
alt = reader.GetDouble();
99+
}
100+
else
101+
{
102+
throw new ArgumentException("Expected number but got other type");
103+
}
104+
105+
// Check what comes next. Expects end of array.
106+
if (!reader.Read())
107+
{
108+
throw new ArgumentException("Expected end of array, but got end of data");
109+
}
110+
if (reader.TokenType != JsonTokenType.EndArray)
111+
{
112+
throw new ArgumentException("Expected 2 or 3 coordinates but got >= 4");
113+
}
114+
115+
return new Position(lat, lng, alt);
48116
}
49117
catch (Exception e)
50118
{
51119
throw new JsonException("Error parsing coordinates", e);
52120
}
53-
return coordinates?.ToPosition() ?? throw new JsonException("Coordinates cannot be null");
54121
}
55122

56123
/// <summary>

0 commit comments

Comments
 (0)