Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/GeoJSON.Text.Test.Unit/GeoJSON.Text.Test.Unit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<None Remove="Feature\GenericFeatureTests_Can_Deserialize_Typed_Point_Feature.json" />
<None Remove="Feature\GenericFeatureTests_Can_Serialize_Typed_Point_Feature.json" />
<None Remove="Geometry\LineStringTests_Can_Deserialize.json" />
<None Remove="Geometry\LineStringTests_Can_Deserialize_Strings.json" />
<None Remove="Geometry\LineStringTests_Can_Deserialize_String_Literals.json" />
<None Remove="Geometry\LineStringTests_Can_Deserialize_With_Altitude.json" />
<None Remove="Geometry\LineStringTests_Can_Serialize.json" />
<None Remove="Geometry\MultiLineStringTests_Can_Deserialize.json" />
<None Remove="Geometry\MultiLineStringTests_Can_Serialize.json" />
Expand All @@ -48,6 +51,8 @@
<EmbeddedResource Include="Feature\GenericFeatureTests_Can_Deserialize_Typed_Point_Feature.json" />
<EmbeddedResource Include="Feature\GenericFeatureTests_Can_Serialize_Typed_Point_Feature.json" />
<EmbeddedResource Include="Geometry\LineStringTests_Can_Deserialize.json" />
<EmbeddedResource Include="Geometry\LineStringTests_Can_Deserialize_Strings.json" />
<EmbeddedResource Include="Geometry\LineStringTests_Can_Deserialize_String_Literals.json" />
<EmbeddedResource Include="Geometry\LineStringTests_Can_Serialize.json" />
<EmbeddedResource Include="Geometry\MultiLineStringTests_Can_Deserialize.json" />
<EmbeddedResource Include="Geometry\MultiLineStringTests_Can_Serialize.json" />
Expand Down Expand Up @@ -76,6 +81,9 @@
<ItemGroup>
<ProjectReference Include="..\GeoJSON.Text\GeoJSON.Text.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Geometry\LineStringTests_Can_Deserialize_With_Altitude.json" />
</ItemGroup>
<ItemGroup>
<None Update="Feature\*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
77 changes: 77 additions & 0 deletions src/GeoJSON.Text.Test.Unit/Geometry/LineStringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,83 @@ public void Can_Deserialize()
Assert.AreEqual(expectedLineString.Coordinates[0].Longitude, actualLineString.Coordinates[0].Longitude);
}

[Test]
public void Can_Deserialize_Strings()
{
var coordinates = new List<IPosition>
{
new Position(52.370725881211314, 4.889259338378906),
new Position(52.3711451105601, 4.895267486572266),
new Position(52.36931095278263, 4.892091751098633),
new Position(52.370725881211314, 4.889259338378906)
};

var expectedLineString = new LineString(coordinates);

var json = GetExpectedJson();
var options = new JsonSerializerOptions { NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString };
var actualLineString = JsonSerializer.Deserialize<LineString>(json, options);

Assert.AreEqual(expectedLineString, actualLineString);

Assert.AreEqual(4, actualLineString.Coordinates.Count);
Assert.AreEqual(expectedLineString.Coordinates[0].Latitude, actualLineString.Coordinates[0].Latitude);
Assert.AreEqual(expectedLineString.Coordinates[0].Longitude, actualLineString.Coordinates[0].Longitude);
}

[Test]
public void Can_Deserialize_With_Altitude()
{
var coordinates = new List<IPosition>
{
new Position(52.370725881211314, 4.889259338378906, 10.0),
new Position(52.3711451105601, 4.895267486572266, 10.5),
new Position(52.36931095278263, 4.892091751098633, null),
new Position(52.370725881211314, 4.889259338378906, 10.2)
};

var expectedLineString = new LineString(coordinates);

var json = GetExpectedJson();
var actualLineString = JsonSerializer.Deserialize<LineString>(json);

Assert.AreEqual(expectedLineString, actualLineString);

Assert.AreEqual(4, actualLineString.Coordinates.Count);
Assert.AreEqual(expectedLineString.Coordinates[0].Latitude, actualLineString.Coordinates[0].Latitude);
Assert.AreEqual(expectedLineString.Coordinates[0].Longitude, actualLineString.Coordinates[0].Longitude);
Assert.AreEqual(expectedLineString.Coordinates[0].Altitude, actualLineString.Coordinates[0].Altitude);
Assert.AreEqual(expectedLineString.Coordinates[2].Altitude, actualLineString.Coordinates[2].Altitude);
}

[Test]
public void Can_Deserialize_String_Literals()
{
var coordinates = new List<IPosition>
{
new Position(52.370725881211314, 4.889259338378906, double.NegativeInfinity),
new Position(52.3711451105601, 4.895267486572266, double.PositiveInfinity),
new Position(52.36931095278263, 4.892091751098633, double.NaN),
new Position(52.370725881211314, 4.889259338378906, double.NegativeInfinity)
};

var expectedLineString = new LineString(coordinates);

var json = GetExpectedJson();
var options = new JsonSerializerOptions { NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals };
var actualLineString = JsonSerializer.Deserialize<LineString>(json, options);

bool b = expectedLineString.Coordinates[0].Equals(actualLineString.Coordinates[0]);
Assert.AreEqual(expectedLineString, actualLineString);

Assert.AreEqual(4, actualLineString.Coordinates.Count);
Assert.AreEqual(expectedLineString.Coordinates[0].Latitude, actualLineString.Coordinates[0].Latitude);
Assert.AreEqual(expectedLineString.Coordinates[0].Longitude, actualLineString.Coordinates[0].Longitude);
Assert.AreEqual(expectedLineString.Coordinates[0].Altitude, actualLineString.Coordinates[0].Altitude);
Assert.AreEqual(expectedLineString.Coordinates[1].Altitude, actualLineString.Coordinates[1].Altitude);
Assert.AreEqual(expectedLineString.Coordinates[2].Altitude, actualLineString.Coordinates[2].Altitude);
}

[Test]
public void Constructor_No_Coordinates_Throws_Exception()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"coordinates": [
[4.8892593383789062, 52.370725881211314, "-Infinity"],
[4.8952674865722656, 52.3711451105601, "Infinity"],
[4.8920917510986328, 52.369310952782627, "NaN"],
[4.8892593383789062, 52.370725881211314, "-Infinity"]
],
"type": "LineString"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"coordinates": [
["4.8892593383789062", "52.370725881211314"],
["4.8952674865722656", "52.3711451105601"],
["4.8920917510986328", "52.369310952782627"],
["4.8892593383789062", "52.370725881211314"]
],
"type": "LineString"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"coordinates": [
[4.8892593383789062, 52.370725881211314, 10.0],
[4.8952674865722656, 52.3711451105601, 10.5],
[4.8920917510986328, 52.369310952782627, null],
[4.8892593383789062, 52.370725881211314, 10.2]
],
"type": "LineString"
}
107 changes: 98 additions & 9 deletions src/GeoJSON.Text/Converters/PositionConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using GeoJSON.Text.Geometry;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand All @@ -28,10 +29,9 @@ public override bool CanConvert(Type objectType)
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param>
/// <param name="reader">The <see cref="T:System.Text.Json.Utf8JsonReader" /> to read from.</param>
/// <param name="type">Type of the object.</param>
/// <param name="options">Serializer options.</param>
/// <returns>
/// The object value.
/// </returns>
Expand All @@ -40,17 +40,106 @@ public override IPosition Read(
Type type,
JsonSerializerOptions options)
{
double[] coordinates;

try
{
coordinates = JsonSerializer.Deserialize<double[]>(ref reader, options);
{
if (reader.TokenType != JsonTokenType.StartArray)
{
throw new ArgumentException("Expected start of array");
}

double lng, lat;
double? alt;

// Read longitude
if (!reader.Read())
{
throw new ArgumentException("Expected number, but got end of data");
}

if (reader.TokenType == JsonTokenType.EndArray)
{
throw new ArgumentException("Expected 2 or 3 coordinates but got 0");
}

if (reader.TokenType == JsonTokenType.Number)
{
lng = reader.GetDouble();
}
else if (reader.TokenType == JsonTokenType.String)
{
lng = JsonSerializer.Deserialize<double>(ref reader, options);
}
else
{
throw new ArgumentException("Expected number but got other type");
}

// Read latitude
if (!reader.Read())
{
throw new ArgumentException("Expected number, but got end of data");
}

if (reader.TokenType == JsonTokenType.EndArray)
{
throw new ArgumentException("Expected 2 or 3 coordinates but got 1");
}

if (reader.TokenType == JsonTokenType.Number)
{
lat = reader.GetDouble();
}
else if (reader.TokenType == JsonTokenType.String)
{
lat = JsonSerializer.Deserialize<double>(ref reader, options);
}
else
{
throw new ArgumentException("Expected number but got other type");
}

// Read altitude, or return if end of array is found
if (!reader.Read())
{
throw new ArgumentException("Unexpected end of data");
}
if (reader.TokenType == JsonTokenType.EndArray)
{
return new Position(lat, lng);
}
else if (reader.TokenType == JsonTokenType.Null)
{
alt = null;
}
else if (reader.TokenType == JsonTokenType.Number)
{
alt = reader.GetDouble();
}
else if (reader.TokenType == JsonTokenType.String)
{
alt = JsonSerializer.Deserialize<double>(ref reader, options);
}
else
{
throw new ArgumentException("Expected number but got other type");
}

// Check what comes next. Expects end of array.
if (!reader.Read())
{
throw new ArgumentException("Expected end of array, but got end of data");
}
if (reader.TokenType != JsonTokenType.EndArray)
{
throw new ArgumentException("Expected 2 or 3 coordinates but got >= 4");
}

return new Position(lat, lng, alt);
}
catch (Exception e)
{
throw new JsonException("Error parsing coordinates", e);
}
return coordinates?.ToPosition() ?? throw new JsonException("Coordinates cannot be null");
}

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion src/GeoJSON.Text/DoubleTenDecimalPlaceComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ public class DoubleTenDecimalPlaceComparer : IEqualityComparer<double>
{
public bool Equals(double x, double y)
{
return Math.Abs(x - y) < 0.0000000001;
return (double.IsNaN(x) && double.IsNaN(y)) ||
(double.IsInfinity(x) && double.IsInfinity(y)) ||
(double.IsNegativeInfinity(x) && double.IsNegativeInfinity(y)) ||
Math.Abs(x - y) < 0.0000000001;
}

public int GetHashCode(double obj)
Expand Down
Loading