Skip to content

Commit

Permalink
Prefix JSON geometry representation with SRID (npgsql#3307)
Browse files Browse the repository at this point in the history
  • Loading branch information
roji authored Sep 30, 2024
1 parent 58608e8 commit 303ffc3
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,18 @@ public override Geometry FromJsonTyped(ref Utf8JsonReaderManager manager, object

/// <inheritdoc />
public override void ToJsonTyped(Utf8JsonWriter writer, Geometry value)
=> writer.WriteStringValue(value.ToText());
{
var wkt = value.ToText();

// If the SRID is defined, prefix the WKT with it (SRID=4326;POINT(-44.3 60.1))
// Although this is a PostgreSQL extension, NetTopologySuite supports it (see #3236)
if (value.SRID > 0)
{
wkt = $"SRID={value.SRID};{wkt}";
}

writer.WriteStringValue(wkt);
}

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
Expand Down
98 changes: 98 additions & 0 deletions test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Collections;
using System.Globalization;
using System.Numerics;
using NetTopologySuite;
using NetTopologySuite.Geometries;
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
using Xunit.Sdk;
Expand Down Expand Up @@ -463,6 +465,102 @@ public virtual Task Can_read_write_LogSequenceNumber_JSON_values(ulong value, st
new NpgsqlLogSequenceNumber(value),
json);

[ConditionalFact]
public override async Task Can_read_write_point()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<PointType, Point>(
nameof(PointType.Point),
factory.CreatePoint(new Coordinate(2, 4)),
"""{"Prop":"SRID=4326;POINT (2 4)"}""");
}

[ConditionalFact]
public virtual async Task Can_read_write_point_without_SRID()
=> await Can_read_and_write_JSON_value<PointType, Point>(
nameof(PointType.Point),
new Point(2, 4),
"""{"Prop":"POINT (2 4)"}""");

[ConditionalFact]
public override async Task Can_read_write_point_with_M()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<PointMType, Point>(
nameof(PointMType.PointM),
factory.CreatePoint(new CoordinateM(2, 4, 6)),
"""{"Prop":"SRID=4326;POINT (2 4)"}""");
}

public override async Task Can_read_write_point_with_Z()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<PointZType, Point>(
nameof(PointZType.PointZ),
factory.CreatePoint(new CoordinateZ(2, 4, 6)),
"""{"Prop":"SRID=4326;POINT Z(2 4 6)"}""");
}

public override async Task Can_read_write_point_with_Z_and_M()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<PointZMType, Point>(
nameof(PointZMType.PointZM),
factory.CreatePoint(new CoordinateZM(1, 2, 3, 4)),
"""{"Prop":"SRID=4326;POINT Z(1 2 3)"}""");
}

[ConditionalFact]
public override async Task Can_read_write_line_string()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<LineStringType, LineString>(
nameof(LineStringType.LineString),
factory.CreateLineString([new Coordinate(0, 0), new Coordinate(1, 0)]),
"""{"Prop":"SRID=4326;LINESTRING (0 0, 1 0)"}""");
}

public override async Task Can_read_write_multi_line_string()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<MultiLineStringType, MultiLineString>(
nameof(MultiLineStringType.MultiLineString),
factory.CreateMultiLineString(
[
factory.CreateLineString(
[new Coordinate(0, 0), new Coordinate(0, 1)]),
factory.CreateLineString(
[new Coordinate(1, 0), new Coordinate(1, 1)])
]),
"""{"Prop":"SRID=4326;MULTILINESTRING ((0 0, 0 1), (1 0, 1 1))"}""");
}

public override async Task Can_read_write_polygon()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<PolygonType, Polygon>(
nameof(PolygonType.Polygon),
factory.CreatePolygon([new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(0, 0)]),
"""{"Prop":"SRID=4326;POLYGON ((0 0, 1 0, 0 1, 0 0))"}""");
}

public override async Task Can_read_write_polygon_typed_as_geometry()
{
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);

await Can_read_and_write_JSON_value<GeometryType, Geometry>(
nameof(GeometryType.Geometry),
factory.CreatePolygon([new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(0, 0)]),
"""{"Prop":"SRID=4326;POLYGON ((0 0, 1 0, 0 1, 0 0))"}""");
}

protected class LogSequenceNumberType
{
public NpgsqlLogSequenceNumber LogSequenceNumber { get; set; }
Expand Down

0 comments on commit 303ffc3

Please sign in to comment.