Skip to content

Commit 303ffc3

Browse files
authoredSep 30, 2024
Prefix JSON geometry representation with SRID (npgsql#3307)
Fixes npgsql#3236
1 parent 58608e8 commit 303ffc3

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed
 

‎src/EFCore.PG.NTS/Storage/Internal/NpgsqlJsonGeometryWktReaderWriter.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,18 @@ public override Geometry FromJsonTyped(ref Utf8JsonReaderManager manager, object
2929

3030
/// <inheritdoc />
3131
public override void ToJsonTyped(Utf8JsonWriter writer, Geometry value)
32-
=> writer.WriteStringValue(value.ToText());
32+
{
33+
var wkt = value.ToText();
34+
35+
// If the SRID is defined, prefix the WKT with it (SRID=4326;POINT(-44.3 60.1))
36+
// Although this is a PostgreSQL extension, NetTopologySuite supports it (see #3236)
37+
if (value.SRID > 0)
38+
{
39+
wkt = $"SRID={value.SRID};{wkt}";
40+
}
41+
42+
writer.WriteStringValue(wkt);
43+
}
3344

3445
/// <inheritdoc />
3546
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);

‎test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs

+98
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.Collections;
44
using System.Globalization;
55
using System.Numerics;
6+
using NetTopologySuite;
7+
using NetTopologySuite.Geometries;
68
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
79
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
810
using Xunit.Sdk;
@@ -463,6 +465,102 @@ public virtual Task Can_read_write_LogSequenceNumber_JSON_values(ulong value, st
463465
new NpgsqlLogSequenceNumber(value),
464466
json);
465467

468+
[ConditionalFact]
469+
public override async Task Can_read_write_point()
470+
{
471+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
472+
473+
await Can_read_and_write_JSON_value<PointType, Point>(
474+
nameof(PointType.Point),
475+
factory.CreatePoint(new Coordinate(2, 4)),
476+
"""{"Prop":"SRID=4326;POINT (2 4)"}""");
477+
}
478+
479+
[ConditionalFact]
480+
public virtual async Task Can_read_write_point_without_SRID()
481+
=> await Can_read_and_write_JSON_value<PointType, Point>(
482+
nameof(PointType.Point),
483+
new Point(2, 4),
484+
"""{"Prop":"POINT (2 4)"}""");
485+
486+
[ConditionalFact]
487+
public override async Task Can_read_write_point_with_M()
488+
{
489+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
490+
491+
await Can_read_and_write_JSON_value<PointMType, Point>(
492+
nameof(PointMType.PointM),
493+
factory.CreatePoint(new CoordinateM(2, 4, 6)),
494+
"""{"Prop":"SRID=4326;POINT (2 4)"}""");
495+
}
496+
497+
public override async Task Can_read_write_point_with_Z()
498+
{
499+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
500+
501+
await Can_read_and_write_JSON_value<PointZType, Point>(
502+
nameof(PointZType.PointZ),
503+
factory.CreatePoint(new CoordinateZ(2, 4, 6)),
504+
"""{"Prop":"SRID=4326;POINT Z(2 4 6)"}""");
505+
}
506+
507+
public override async Task Can_read_write_point_with_Z_and_M()
508+
{
509+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
510+
511+
await Can_read_and_write_JSON_value<PointZMType, Point>(
512+
nameof(PointZMType.PointZM),
513+
factory.CreatePoint(new CoordinateZM(1, 2, 3, 4)),
514+
"""{"Prop":"SRID=4326;POINT Z(1 2 3)"}""");
515+
}
516+
517+
[ConditionalFact]
518+
public override async Task Can_read_write_line_string()
519+
{
520+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
521+
522+
await Can_read_and_write_JSON_value<LineStringType, LineString>(
523+
nameof(LineStringType.LineString),
524+
factory.CreateLineString([new Coordinate(0, 0), new Coordinate(1, 0)]),
525+
"""{"Prop":"SRID=4326;LINESTRING (0 0, 1 0)"}""");
526+
}
527+
528+
public override async Task Can_read_write_multi_line_string()
529+
{
530+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
531+
532+
await Can_read_and_write_JSON_value<MultiLineStringType, MultiLineString>(
533+
nameof(MultiLineStringType.MultiLineString),
534+
factory.CreateMultiLineString(
535+
[
536+
factory.CreateLineString(
537+
[new Coordinate(0, 0), new Coordinate(0, 1)]),
538+
factory.CreateLineString(
539+
[new Coordinate(1, 0), new Coordinate(1, 1)])
540+
]),
541+
"""{"Prop":"SRID=4326;MULTILINESTRING ((0 0, 0 1), (1 0, 1 1))"}""");
542+
}
543+
544+
public override async Task Can_read_write_polygon()
545+
{
546+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
547+
548+
await Can_read_and_write_JSON_value<PolygonType, Polygon>(
549+
nameof(PolygonType.Polygon),
550+
factory.CreatePolygon([new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(0, 0)]),
551+
"""{"Prop":"SRID=4326;POLYGON ((0 0, 1 0, 0 1, 0 0))"}""");
552+
}
553+
554+
public override async Task Can_read_write_polygon_typed_as_geometry()
555+
{
556+
var factory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
557+
558+
await Can_read_and_write_JSON_value<GeometryType, Geometry>(
559+
nameof(GeometryType.Geometry),
560+
factory.CreatePolygon([new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(0, 1), new Coordinate(0, 0)]),
561+
"""{"Prop":"SRID=4326;POLYGON ((0 0, 1 0, 0 1, 0 0))"}""");
562+
}
563+
466564
protected class LogSequenceNumberType
467565
{
468566
public NpgsqlLogSequenceNumber LogSequenceNumber { get; set; }

0 commit comments

Comments
 (0)
Please sign in to comment.