Coder Social home page Coder Social logo

nettopologysuite.io.geojson's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nettopologysuite.io.geojson's Issues

Self referencing loop detected with type 'NetTopologySuite.Features.AttributesTable'. Path '[257].properties'.

I'm not sure what causes this as the stack trace from my server is hot helping but since I upgraded to 2.0 I see a lot of the following error in the log file:
Self referencing loop detected with type 'NetTopologySuite.Features.AttributesTable'. Path '[x].properties'.
Any change you guys know what can cause this?
The number in the [x] is a changing number.
This happens when the server returns a geojson to the client.
The following is the stacktrace:

at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeConvertable(JsonWriter writer, JsonConverter converter, Object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at NetTopologySuite.IO.Converters.AttributesTableConverter.WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeConvertable(JsonWriter writer, JsonConverter converter, Object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at NetTopologySuite.IO.Converters.FeatureConverter.WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeConvertable(JsonWriter writer, JsonConverter converter, Object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
   at Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

Any help would be appreciated...

Converters fail to handle JsonToken.Comment

In an attempt to solve #6 it became obvious that the used converters don't handle JsonToken.Comment at all.

Here is an example:

{
  // here we go
  "id": "featureID",
  // A feature
  "type": "Feature",
  // Its geometry
  "geometry": {
     // look, its a point
    "type": "Point",
     // where is it
    "coordinates": [50.77, 6.11]
     // ah in Aix la Chapelle
  }
  // no more comments
 }

Document how to use IO.GeoJSON in combination with ASP.NET Core

From @dalbani on March 1, 2018 11:34

It would be nice to have some documentation on how to use NetTopologySuite.IO.GeoJSON in combination with ASP.NET Core.
I've managed to configure the MVC engine to produce GeoJSON using NTS serializer, but I couldn't get it to consume GeoJSON to work.

Here's some pseudo-code of what I did to configure MVC:

namespace MyApp
{
    public class Startup
    {
        // ...
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
        }
        // ...
    }

    public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
    {
        private readonly ILogger<MvcOptions> _logger;
        private readonly ObjectPoolProvider _objectPoolProvider;

        public ConfigureMvcOptions(ILogger<MvcOptions> logger, ObjectPoolProvider objectPoolProvider)
        {
            _logger = logger;
            _objectPoolProvider = objectPoolProvider;
        }

        public void Configure(MvcOptions mvcOptions)
        {
            mvcOptions.InputFormatters.Insert(0, new GeoJsonInputFormatter(
                _logger, new JsonSerializerSettings(), ArrayPool<char>.Shared, _objectPoolProvider));

            mvcOptions.OutputFormatters.Insert(0, new GeoJsonOutputFormatter(
                new JsonSerializerSettings
                {
                    // omit "crs: null" properties in GeoJSON output
                    NullValueHandling = NullValueHandling.Ignore
                }, ArrayPool<char>.Shared));
        }
    }
}

The GeoJSON input/output formatters:

namespace MyApp.Formatters
{
    public class GeoJsonInputFormatter : JsonInputFormatter
    {
        public GeoJsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings,
            ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, bool suppressInputFormatterBuffering = false)
            : base(logger, serializerSettings, charPool, objectPoolProvider, suppressInputFormatterBuffering)
        {
            SupportedMediaTypes.Clear();
            SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/geo+json"));
        }

        protected override JsonSerializer CreateJsonSerializer()
        {
            return GeoJsonSerializer.Create(SerializerSettings, GeometryFactory.Default);
        }
    }

    public class GeoJsonOutputFormatter : JsonOutputFormatter
    {
        public GeoJsonOutputFormatter(JsonSerializerSettings serializerSettings, ArrayPool<char> charPool)
            : base(serializerSettings, charPool)
        {
            SupportedMediaTypes.Clear();
            SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/geo+json"));
        }

        protected override JsonSerializer CreateJsonSerializer()
        {
            return GeoJsonSerializer.Create(SerializerSettings, GeometryFactory.Default);
        }
    }
}

And a controller:

namespace MyApp.Controllers
{
    [Route("[controller]")]
    public class MyController : Controller
    {
        [HttpPost]
        [Consumes("application/geo+json")]
        [Produces("application/geo+json")]
        [ProducesResponseType(typeof(FeatureCollection), 200)]
        public IActionResult Post([FromBody] FeatureCollection featureCollection /* or Feature feature */)
        {
            return Ok(featureCollection); // the featureCollection object is always null here?!
        }
    }
}

Yet, setting a TraceWriter on the JSON serializer, I could confirm that the GeoJSON was successfully parsed.
But somewhere in ASP.NET / MVC is the FeatureCollection object not properly passed back to the controller's function.
Is there any experts in the room? :-)

I'm using the latest 1.15.0 pre-release version, in combination with ASP.NET Core 2.0 (on Linux).

Thanks for your help!

Copied from original issue: NetTopologySuite/NetTopologySuite#215

Update to latest NTS Core

There are some important bug fixes in the latest 1.15.2 version of the NTS Core package. Can you please ship a new version that references that one?

How to serializer a .NET Core class via a FeatureCollection to valid GeoJSON

I'm not sure if this is the right place to ask questions.
I also asked on StackOverflow (https://stackoverflow.com/questions/52671754/serialize-data-from-postgis-to-json) so far no response.

I'm struggling with this for days now.

I have a simple .NET Core class with a NTS Point.
I need to serialize this as GeoJSON in my controller to feed a Leaflet map.
I'm trying to create a GeoJson like this: https://geodata.nationaalgeoregister.nl/wijkenbuurten2014/ows?service=WFS&version=2.0.0&request=GetFeature&outputFormat=application/json&srsName=EPSG:4326&typeName=wijkenbuurten2014:cbs_buurten_2014&propertyName=buurtnaam,personenautos_per_huishouden,geom&cql_filter=gemeentenaam%20=%20%27Utrecht%27 because that one is working.

In the SO post I have posted all relevant code but I'm having a hard time to do this seemingly simple task.

My class

    public class Location
    {
        public int Id { get; set; }
        public string LocationId { get; set; }
        public bool Use { get; set; }
        public Point Location { get; set; }
    }

My ToFC method:

        public FeatureCollection GetLocationsAsFeatureCollection()
        {
            var featureCollection = new FeatureCollection();
            foreach (var sobekLocation in GetLocations())
            {
                var attr = new AttributesTable
                {
                    {"Id", sobekLocation.Id},
                    {"Use", sobekLocation.Use},
                    {"LocationId", sobekLocation.LocationId}
                };

                var feature = new Feature(sobekLocation.Location, attr);
                featureCollection.Add(feature);
            }

            return featureCollection;
        }

My serialize code:

var fc = _applicationDataService.GetLocationsAsFeatureCollection();
var sb = new StringBuilder();
var jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings
{
    // NullValueHandling = NullValueHandling.Ignore, 
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    ContractResolver = new CamelCasePropertyNamesContractResolver()
});

using (var sw = new StringWriter(sb))
{
    jsonSerializer.Serialize(sw, fc);
}

return Ok(sb.ToString());

The GeoJSON produced doesn't have the "type": "Feature",, the attributes should be in properties but are in attributes.

A good working example would be much appreciated since I could not find any.

Converter attribute ("StjGeometryConverter")

I would really like to be able to decorate a property in my class with the converter. For example:
[JsonConverter(typeof(GeometryConverter))]
public Geometry Location { get; set; }
The converter I'd like to use is "StjGeometryConverter", but it is only available internally or via a factory ("GeoJsonConverterFactory").

Is there a way to use that converter in an attribute, even if it is only exposed by a factory?

Alternatively, is there a reason that converter isn't public?

4STJ Serialization Modifies Polygon Shell.IsCCW

//Set the SRID so the DB known this is geography
polygon.SRID = GeometryHelper.SpatialReferenceId;

polygon.Normalize();

//The polygons which are going to the DB must be in CCW order.
if (false == polygon.Shell.IsCCW)
{
	polygon = polygon.Reverse() as Polygon;
}

I have this code preceding code which serialized to geojson

//Write the Polygon to a geojson file
using (var fileStream = File.Create("polygonutf8.geojson"))
{
	using (var utf8JsonWriter = new System.Text.Json.Utf8JsonWriter(fileStream, new System.Text.Json.JsonWriterOptions()
	{
		Indented = true
	}))
	{
		System.Text.Json.JsonSerializer.Serialize(utf8JsonWriter, new FeatureCollection() { { new Feature(polygon, null) } }, JsonSerializerOptions);
	}
}

After which the polygonShell.IsCCW is false somehow..

I have to again run:

polygon.Normalize();

//The polygons which are going to the DB must be in CCW order.
if (false == polygon.Shell.IsCCW)
{
	polygon = polygon.Reverse() as Polygon;
}

I have not looked into the code to see where or why this occurs.

But I know i did not have to do this until I switched to the 4stj version of the project.

Incorrect GeoJson deserialization in ASP.NET Core

I'm currently stucked with this issue and absolutely can't figure out how to properly work with GeoJsonSerializer in ASP.NET Core.

Here is my simple extension, which enables GeoJson serialization:

        public static MvcJsonOptions AddGeoJsonConverters(this MvcJsonOptions options)
        {
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            var converters = GeoJsonSerializer.Create(
                new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore },
                new GeometryFactory(new PrecisionModel(), 4326)).Converters;

            foreach (var converter in converters)
            {
                options.SerializerSettings.Converters.Add(converter);
            }

            return options;
        }

It perfectly works on serialization, unfortunately deserialization throws the exception:

Unable to find a constructor to use for type NetTopologySuite.Geometries.LineString. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.

What else I supposed to set up to properly deserialize GeoJson?

Cannot serialize GeometryCollection with GeometryConverter

Attempting to serialize GEOMETRYCOLLECTION(POINT(543651.38 6360876.03 18.14),POINT(543653.18 6360875.57 18.11)) with the GeometryConverter results in error:

Newtonsoft.Json.JsonWriterException : Token StartArray in state Object would result in an invalid JSON object. Path ''.

.NET number values such as positive and negative infinity cannot be written as valid JSON.

I'm trying to serialize a feature with a dictionary and a point and receive this error. I'm not sure if it is related to bounding box or envelope which are empty. Any thoughts on whats up? Nice job on the standup otherwise I wouldn't have known about this library. I'm coming from geojson.net.

I tried this with just a point and it fails with the same message also so I would assume that the point is the cause of the issue.

var feature = new Feature(new Point(1, 2), new AttributesTable());

with

.AddJsonOptions(options => {
                // open api is currently using system.text.json
                options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
                options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
                options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
            });
[ERR 17:31:50] (Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) An unhandled exception has occurred while executing the request. 
System.ArgumentException: .NET number values such as positive and negative infinity cannot be written as valid JSON.
   at System.Text.Json.ThrowHelper.ThrowArgumentException_ValueNotSupported()
   at System.Text.Json.Utf8JsonWriter.WriteNumberValue(Double value)
   at System.Text.Json.Serialization.Converters.DoubleConverter.Write(Utf8JsonWriter writer, Double value, JsonSerializerOptions options)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteCore[TValue](JsonConverter jsonConverter, Utf8JsonWriter writer, TValue& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteAsyncCore[TValue](Stream utf8Json, TValue value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Deserialize object inside properties

I'm not sure if this is possible or not, and if this requires some implementation.
Here's the gist of it:
I want to set an object inside the attributes table (properties) and get it back after serialization and deserialization.
Something like the following test:

        [TestMethod]
        public void Test()
        {
            var feature = new Feature(new Point(0, 0), new AttributesTable
            {
                { "data", new MyClass { MyProp = new MyProp { A = new DateTime()}} }
            });
            var bytes = new FeatureCollection { feature }.ToBytes(); //serialize
            var coll = bytes.ToFeatureCollection(); // deserialize
            Assert.IsTrue(coll[0].Attributes["data"] is MyClass);
        }

`POLYGON Empty` etc

Consider:

SELECT geography::STGeomFromText('POLYGON EMPTY', 4326)

Consider this code:

using var (testOut= File.Create(".test.geojson"))
			{
				using (var utf8JsonWriter = new System.Text.Json.Utf8JsonWriter(testOut))
				{
					System.Text.Json.JsonSerializer.Serialize(utf8JsonWriter, new FeatureCollection() { new Feature(new NetTopologySuite.IO.WKTReader().Read("POLYGON EMPTY"), new AttributesTable() { { "test", "1" } }) }, JsonSerializerOptions);
				}
			}

The Polygon is not valid so an exception is thrown and the program crashes...

Seems like the problem comes from something in the base library.

See: NetTopologySuite/NetTopologySuite#422

I think it's also important to have sentinels for Geometry.Empty which would make working with null a lot nicer.

Issue with bbox being outputted as null when NullHandling is set to Include

There is an issue with FeatureConverter where bbox element is being outputted without any value in case NullValueHandling is set to Include and feature does not have a bounding box specified. This produces an invalid geojson. The element should either be omitted or be populated with an array. Snippet causing the issue is below:

// bbox (optional)
if (serializer.NullValueHandling == NullValueHandling.Include || feature.BoundingBox != null)
{
writer.WritePropertyName("bbox");
serializer.Serialize(writer, feature.BoundingBox, typeof(Envelope));
}

3D point serialization exception

The following test fails after I migrated to NTS 2.0:

[TestMethod]
        public void Test3DPointSerialization()
        {
            var featureCollection = new FeatureCollection { new Feature(new Point(new CoordinateZ(1, 2, 3)), new AttributesTable()) };
            using (var outputStream = new MemoryStream())
            {
                var writer = new StreamWriter(outputStream);
                var jsonWriter = new JsonTextWriter(writer);
                var serializer = GeoJsonSerializer.CreateDefault();
                serializer.Serialize(jsonWriter, featureCollection);
            }
        }

Might be related to #4 but this stopped working only after migration to 2.0.
I have tried several GeoJsonSerializer.Create(...) methods, none of them worked...

Serialization issue with GeoJson Point

From @HarelM on March 19, 2017 0:19

The following test throws exceptions:

        [Test]
        public void SerializationTest()
        {
            var featureCollection = new FeatureCollection { Features = { new Feature(new Point(new Coordinate(1, 2, 3)), new AttributesTable()) } };
            using (var outputStream = new MemoryStream())
            {
                var writer = new StreamWriter(outputStream);
                var jsonWriter = new JsonTextWriter(writer);
                var serializer = GeoJsonSerializer.Create();
                serializer.Serialize(jsonWriter, featureCollection);
                jsonWriter.Flush();
                Assert.IsNotNull(outputStream.ToArray());
            }
        }

The following is the exception:

Newtonsoft.Json.JsonSerializationException : Self referencing loop detected for property 'CoordinateValue' with type 'GeoAPI.Geometries.Coordinate'. Path 'Features[0].Geometry.Coordinates[0]'.
   at ...

This is the code I previously used to change feature collection to string and then to bytes...
Not sure If I should do something else since this is .Net Core...?
Happens on net_refactoring branch, haven't tested stable version.

Copied from original issue: NetTopologySuite/NetTopologySuite#162

4STJ could use an equivalent to TryGetJsonObjectPropertyValue for the entire attributes table

Consider this feature:

{
	"type": "Feature",
	"geometry": {
		"type": "Point",
		"coordinates": [10, 20]
	},
	"properties": {
		"secondsToCompute": 2.4,
		"age": 34,
		"hireDate": "2009-01-01",
		"name": "Kyle"
	}
}

I would like to be able to do something like this:

void DoStuff(IFeature deserializedFeature, JsonSerializerOptions options)
{
	if (!deserializedFeature.Attributes.TryDeserializeJsonObject(options, out Employee employee))
	{
		throw new JsonException("doesn't work");
	}

	DoStuffWith(employee);
}

The best I can do right now in 2.0.4, given that I can't change the code that's producing the GeoJSON feature values, is something like this:

void DoStuff(IFeature deserializedFeature, JsonSerializerOptions options)
{
    var employee = new Employee
    {
        SecondsToCompute = feature.Attributes.TryGetJsonObjectPropertyValue("secondsToCompute", opts, out double secondsToCompute) ? secondsToCompute : throw new JsonException(),
        Age = feature.Attributes.TryGetJsonObjectPropertyValue("age", opts, out int age ) ? age : throw new JsonException(),
        Name = feature.Attributes.TryGetJsonObjectPropertyValue("name", opts, out string name) ? name : throw new JsonException(),
        HireDate = feature.Attributes.TryGetJsonObjectPropertyValue("hireDate", opts, out DateTime hireDate) ? hireDate : throw new JsonException(),
    };

	DoStuffWith(employee);
}

That last snippet is really annoying: there can be very many properties, and it's frankly just a lot of code to have to write that I normally don't have to write for other very similar use cases that don't put info in their GeoJSON features.

Wrong SRID after deserializing

Hi,

After deserializing a geojson object the SRID is 0 by default. But according to the geojson specs the
coordinate reference system is WGS 84, meaning SRID 4326.

Shouldn't it be more logic and correct if the default GeometryFactory used by the GeoJsonSerializer would have 4326 as SRID.

AddGeoJsonConverters(s, GeometryFactory.Default);

So instead of GeometryFactory.Default use new GeometryFactory(new PrecisionModel(), 4326).

Regards,

Jochen

ArgumentException : 'Expected value 'Feature' not found' when we try to read GeoJson

Hello :) ,

  • project to reproduce bug in attachment : nettopologysuitetests.zip

  • input exemple : "{"type":"Feature", "properties":{}, "geometry":{"type":"Polygon", "coordinates":[[[2.329444885254, 48.849334716797], [2.3412895202638, 48.84916305542], [2.340431213379, 48.841953277588], [2.3278999328614, 48.841953277588], [2.329444885254, 48.849334716797]]]}, "crs":{"type":"name", "properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}}"

-stacktrace : ร  NetTopologySuite.IO.Converters.FeatureConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) dans D:\Development\Source\Repos\NTS.IO\NetTopologySuite.IO.GeoJSON\NetTopologySuite.IO.GeoJSON\Converters\FeatureConverter.cs:ligne 95
ร  Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
ร  Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
ร  Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
ร  Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
ร  NetTopologySuite.IO.GeoJsonReader.Read[TObject](String json) dans D:\Development\Source\Repos\NTS.IO\NetTopologySuite.IO.GeoJSON\NetTopologySuite.IO.GeoJSON\GeoJsonReader.cs:ligne 50

Issue when parsing a geometry with coordinates containing null

There seems to be an issue in GeometryConverter class when parsing coordinates containing null. When this happens, the code goes into an infinite loop.

Here is a sample JSON that causes the infinite loop: {"structureId":"","geometry3857":{"type":"Point","coordinates":[null,null]},"isCulvert":false}

And the issue is in the following snippet:

while (reader.TokenType != JsonToken.EndArray)
            {
                if (reader.TokenType == JsonToken.StartArray)
                {
                    coords.Add(ReadCoordinates(reader));
                }
                else if (reader.Value != null)
                {
                    coords.Add(reader.Value);
                    reader.Read();
                }
            }

Error on GeoJsonReader because referencing wrong version of Newtonsoft

From a clean install of version 1.14.0
though same issur occurs with V1.15.0-pre063
you get the following error when calling GeoJsonReader.Read
System.IO.FileNotFoundException
HResult=0x80070002
Message=Could not load file or assembly 'Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
Source=NetTopologySuite.IO.GeoJSON
StackTrace:
at NetTopologySuite.IO.GeoJsonReader.Read[TObject](String json)

as its only installed 3.5.8

updating to version 11.0.2 (latest stable) of newtonsoft throws error @ Creation of a GeoJsonReader
System.IO.FileNotFoundException
HResult=0x80070002
Message=Could not load file or assembly 'Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
Source=NetTopologySuite.IO.GeoJSON
StackTrace:
at NetTopologySuite.IO.GeoJsonReader..ctor()

Inner Exception 1:
FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.

manually forcing the version to 9.0.1 fixes

[Bug] Read json Whosfirst data

Error:
Self referencing loop detected with type 'NetTopologySuite.Features.AttributesTable'. Path 'properties.wof:hierarchy

{
  "id": 1108782367,
  "type": "Feature",
  "properties": {
    "edtf:cessation":"uuuu",
    "edtf:inception":"uuuu",
    "geom:area":0.089812,
    "geom:area_square_m":1083122630.17205,
    "geom:bbox":"27.7311019512,-12.9025374885,28.1515905025,-12.5626803075",
    "geom:latitude":-12.757096,
    "geom:longitude":27.940252,
    "iso:country":"ZM",
    "lbl:latitude":-12.781612,
    "lbl:longitude":27.9823,
    "meso:adm1_en":"Copperbelt",
    "meso:dissme":"CopperbeltKalulushi",
    "meso:gadm_adm2":"Kalulushi",
    "meso:gaul_adm2":"Kalulushi",
    "meso:hasc_id":"ZM.CO.KU",
    "meso:mps_x":27.9823,
    "meso:mps_y":-12.781612,
    "meso:name_en":"Kalulushi",
    "meso:source":"AOTM",
    "mps:latitude":-12.781612,
    "mps:longitude":27.9823,
    "mz:hierarchy_label":1,
    "mz:is_current":1,
    "name:eng_x_preferred":[
        "Kalulushi"
    ],
    "src:geom":"meso",
    "src:lbl:centroid":"mapshaper",
    "src:population":"statoids",
    "src:population:date":"2010-10-16",
    "statoids:area_km":"725",
    "statoids:as_of_date":"2010-10-16",
    "statoids:capital":"",
    "statoids:country":"ZM",
    "statoids:hasc":"ZM.CO",
    "statoids:name":"Kalulushi",
    "statoids:population":"100381",
    "statoids:statoid":"ZM.CO.KU",
    "statoids:timezone":"2",
    "statoids:type":"district",
    "wof:belongsto":[
        102191573,
        85632559,
        85681063
    ],
    "wof:breaches":[],
    "wof:concordances":{
        "hasc:id":"ZM.CO.KU"
    },
    "wof:country":"ZM",
    "wof:created":1481743471,
    "wof:geomhash":"af68b61cc72649f5645b2b8e04a39fb2",
    "wof:hierarchy":[
        {
            "continent_id":102191573,
            "country_id":85632559,
            "county_id":1108782367,
            "region_id":85681063
        }
    ],
    "wof:id":1108782367,
    "wof:lastmodified":1536615772,
    "wof:name":"Kalulushi",
    "wof:parent_id":85681063,
    "wof:placetype":"county",
    "wof:placetype_local":"district",
    "wof:population":100381,
    "wof:population_rank":9,
    "wof:repo":"whosonfirst-data",
    "wof:shortcode":"KU",
    "wof:superseded_by":[],
    "wof:supersedes":[],
    "wof:tags":[]
},
  "bbox": [
    27.73110195115867,
    -12.90253748851593,
    28.15159050246744,
    -12.56268030752129
],
  "geometry": {"coordinates":[[[27.73188815898529,-12.64069314550956],[27.7390221354787,-12.6414954260402],[27.74044893077738,-12.64165588214633],[27.7421610851358,-12.64184842947368],[27.7442156703659,-12.64207948626651],[27.74668117264201,-12.64235675441789],[27.74963977537335,-12.64268947619956],[27.75319009865097,-12.64308874233756],[27.75628623399668,-12.6436378709011],[27.7590583590219,-12.64428163895435],[27.7615439528957,-12.64489875505008],[27.763808761916,-12.64558401294571],[27.76590833459249,-12.64624733389161],[27.76786652451949,-12.64695265218795],[27.76986523470625,-12.64771584311077],[27.77202215843274,-12.64856676626116],[27.77415837499198,-12.64955070997992],[27.77627222539789,-12.65062277699697],[27.77838864563085,-12.65185512298975],[27.78038352706829,-12.65311059928275],[27.78232523487959,-12.65446881694796],[27.78425587165304,-12.65589029394243],[27.78611320296324,-12.65736788738829],[27.78804087791672,-12.65887140749645],[27.78988246871902,-12.66033200742111],[27.79166119687786,-12.66175518942712],[27.79336310670377,-12.66319628823641],[27.79507577962397,-12.66477729751984],[27.79678797772725,-12.66650422083819],[27.79847973297302,-12.66845710820542],[27.8000435414512,-12.67031289159249],[27.80150666621222,-12.67218498958811],[27.80284324668533,-12.67400796804177],[27.80418576578839,-12.67585352315153],[27.80548965130081,-12.67763149743812],[27.80689308103555,-12.67953996474893],[27.80840966426678,-12.68151560341627],[27.81006553482348,-12.68366077615155],[27.81172256256287,-12.68579440257965],[27.81351026020119,-12.68800033247005],[27.81538086368771,-12.69004507584036],[27.81749135763689,-12.69208264205614],[27.81975280994722,-12.6941454440496],[27.82209769186993,-12.69609387805957],[27.82465776255325,-12.69810147636077],[27.82731831506651,-12.70018268172722],[27.83004027579599,-12.70158578895642],[27.83301563527538,-12.70271299773799],[27.83635004652439,-12.70379023422269],[27.83954405930015,-12.70457266364123],[27.84280551319037,-12.70521413726821],[27.84623240135084,-12.7058208520904],[27.84959733502304,-12.7065868746328],[27.8532081869289,-12.7074972801476],[27.85669703661385,-12.70837836255102],[27.86043680509118,-12.70924926654083],[27.86400754527174,-12.70964627068678],[27.86755834827694,-12.70974274000809],[27.87095025755333,-12.7097000238837],[27.87400161860205,-12.70990682165222],[27.87694899790303,-12.71012314844229],[27.88011527771834,-12.71035061614587],[27.88288515526632,-12.71024770794457],[27.88552863853339,-12.70990837976187],[27.88818276549074,-12.70944466092203],[27.8906592197142,-12.70875484227914],[27.8932644565131,-12.70785563450521],[27.89546045789455,-12.70686608669724],[27.89760748610894,-12.70576283005017],[27.89956680393752,-12.70486776617775],[27.90143013791623,-12.7041093212534],[27.90330699709118,-12.70339007366953],[27.90534954212104,-12.70264189455318],[27.90750845392424,-12.70182148699866],[27.90959868184401,-12.70081053579174],[27.91160205056997,-12.69962175225331],[27.91340426812468,-12.69844216541053],[27.91524662901485,-12.6971511474638],[27.91697231179695,-12.69571824905446],[27.91878292376468,-12.69407016153413],[27.92065534856525,-12.69223339024454],[27.92249012726143,-12.69047223658264],[27.924293187995,-12.68871016667653],[27.92622488612746,-12.68684353099263],[27.92801556234426,-12.68505289984686],[27.92975891386412,-12.6833406049513],[27.9315234259531,-12.6815442340656],[27.93302102532257,-12.67998694068375],[27.93446965243072,-12.67847382263546],[27.93602491653585,-12.67685633908669],[27.93754366453145,-12.67519643766063],[27.93911903039994,-12.67346339750737],[27.94055320242819,-12.6717396100446],[27.94191002511908,-12.67001292746067],[27.94330337937949,-12.66814219223982],[27.94480203525446,-12.66605827744548],[27.94624461734777,-12.66405347109975],[27.94779797560049,-12.6619713290597],[27.94937052057394,-12.65995573871614],[27.95095549074832,-12.65791811175698],[27.9525466034248,-12.65595399257367],[27.95421378376226,-12.6539196383161],[27.95606683032719,-12.65169095979483],[27.9580258942365,-12.64925769617947],[27.95996082130496,-12.64683686722385],[27.96202629249483,-12.64445167382741],[27.96397266688771,-12.64210320353874],[27.9659025538067,-12.64000777735438],[27.9677235644378,-12.63811802570631],[27.96965575222825,-12.6361796291073],[27.97155868522955,-12.63436518930453],[27.9734426549009,-12.63252504985033],[27.97526095939094,-12.63095579722062],[27.97720092973096,-12.6294390613034],[27.97928812572281,-12.6279110068807],[27.98157327639142,-12.62628077498439],[27.98397312416806,-12.62465490518602],[27.98659175853804,-12.62293444185105],[27.98957112304561,-12.62105930495263],[27.99238190928828,-12.61936428516113],[27.99520969715126,-12.61774368342135],[27.9977260728208,-12.61596217345998],[28.00015202414984,-12.61401740053303],[28.00267026345773,-12.61188908996632],[28.00535940992675,-12.60979746053877],[28.00783011989641,-12.60795297191718],[28.0103672728199,-12.6061553257623],[28.01287614209096,-12.60444357279325],[28.01553480796996,-12.60268735625471],[28.01825681410752,-12.60088152628531],[28.0209887509404,-12.59930266896114],[28.0238108756141,-12.59781972897656],[28.02684398959617,-12.59664410605859],[28.02970642351856,-12.5958879458566],[28.03241024493212,-12.59534104226774],[28.03510248569205,-12.59483464055247],[28.03767842653963,-12.59415777886391],[28.04000884737997,-12.59335070569159],[28.04241463462124,-12.59238407046604],[28.04506342116151,-12.59123973841863],[28.04768598604539,-12.58987950308966],[28.05028711919328,-12.58834998534002],[28.05288048925317,-12.58712162830044],[28.05521114761514,-12.58629363247815],[28.05738023020742,-12.58572022467471],[28.05963386960307,-12.58522883957304],[28.06172573387196,-12.5846203294621],[28.06368817746996,-12.58388367994649],[28.06574101129488,-12.58301422690083],[28.06780028307416,-12.58218686791366],[28.06976383788869,-12.58132199440741],[28.07178722001204,-12.5803657329587],[28.07362259937446,-12.57948785598565],[28.07550649436397,-12.57857778495509],[28.07747654393215,-12.5777290597736],[28.07965844976512,-12.57684821875255],[28.08166764009957,-12.5759728676692],[28.08367564324652,-12.57508177818465],[28.08570942915338,-12.57413166670234],[28.08779163646585,-12.57319515409205],[28.08987166976793,-12.5722383684896],[28.09170172359399,-12.57138244239523],[28.09355474258231,-12.57051753210756],[28.09555201482437,-12.56961913329085],[28.09777232008365,-12.56866272882465],[28.09982418217454,-12.56789348986464],[28.10194391959658,-12.56716686990233],[28.10414649891324,-12.56655207150482],[28.10637197929999,-12.56593068086307],[28.10859822822735,-12.56526000654269],[28.11066255811618,-12.56459045305001],[28.11278459298465,-12.56390726896595],[28.114925689281,-12.56328062873153],[28.1170133103263,-12.56268030752129],[28.11804634323597,-12.56452387141269],[28.11951605400045,-12.56625457728332],[28.12120115036904,-12.56783484783076],[28.12288378541681,-12.56945973379081],[28.12444182175259,-12.57118498073922],[28.1258387317244,-12.57296685595234],[28.12695841298459,-12.57479337874488],[28.12792736172728,-12.57657959365208],[28.12880952914276,-12.57857338608952],[28.12962168122968,-12.58043372366387],[28.13038040122775,-12.5822537910062],[28.13112223955653,-12.58415128981294],[28.13190282699605,-12.58599151266553],[28.13276899689238,-12.58784660112237],[28.13385608520537,-12.58999080271875],[28.13476194605953,-12.59236882822711],[28.13505262832324,-12.5947813469036],[28.13458599117249,-12.5973400286688],[28.13424772739663,-12.59976058576919],[28.13414446650577,-12.60217122584598],[28.13439624640475,-12.60460184139404],[28.1349507568272,-12.60700209369256],[28.13575142692403,-12.6092517946],[28.13658206647031,-12.61140008759752],[28.13739411708855,-12.61351742116837],[28.13811923324027,-12.61563007115434],[28.13881496334703,-12.61800567259494],[28.13936864204126,-12.62030498146237],[28.13974983242905,-12.62281972489492],[28.14005548474821,-12.62533730752399],[28.14027211584505,-12.62776600611364],[28.14037506531205,-12.63044634560749],[28.14061970668894,-12.63329070480004],[28.14096246958474,-12.63596423159687],[28.14156084139648,-12.63847205971343],[28.14241180749246,-12.64089021991123],[28.14364677526815,-12.64334641836826],[28.14497072980137,-12.6458542902898],[28.14607402524571,-12.64794418355775],[28.146993438116,-12.64968576128105],[28.14775961550791,-12.65113707605046],[28.14839809666783,-12.65234650502497],[28.1489301643011,-12.65335436250373],[28.15159050246744,-12.65839364989751],[28.1499471133689,-12.66052493907424],[28.14847311657981,-12.6624774349624],[28.14710017600288,-12.66437022814369],[28.1456683992529,-12.66647826637011],[28.14422076985976,-12.66891528178376],[28.14283137800391,-12.67121418685101],[28.14148792936157,-12.67352476821409],[28.14017359976231,-12.67571597521201],[28.13882511427862,-12.67790892763486],[28.13744846803905,-12.68002933176296],[28.13594516370289,-12.68222092371711],[28.13418013784614,-12.68438658373539],[28.13220186491775,-12.68655069392077],[28.13045856785905,-12.68884555139379],[28.12882190186694,-12.69117815167947],[28.1272020829859,-12.69356366981513],[28.12555534260589,-12.69598360830909],[28.12404226177502,-12.69822091609126],[28.12263945513191,-12.70046365786369],[28.1212719036802,-12.7029372431793],[28.11993796493207,-12.70547042352091],[28.11875690402712,-12.70793580153205],[28.11768817204216,-12.71032277286942],[28.1166240739709,-12.7125161117167],[28.11541683626692,-12.71469720622521],[28.11397199418041,-12.71714170886027],[28.11267136953163,-12.71987202643631],[28.11175690384163,-12.72256448771445],[28.11136142679365,-12.72538799316184],[28.11092288981288,-12.72810567563196],[28.11028590120591,-12.73094176641596],[28.10920643156706,-12.7337132719927],[28.10820685524473,-12.73631001027104],[28.10730689170727,-12.73881090943415],[28.10645875706274,-12.74141155715393],[28.10573550315022,-12.74424238891034],[28.10518065459568,-12.74717594550193],[28.10472317997954,-12.75017618936307],[28.10402930094724,-12.75300390808063],[28.10301911384327,-12.75574059106143],[28.10193570541376,-12.75856698132333],[28.10083734597388,-12.76158106975791],[28.09992862213697,-12.76461449081243],[28.09925284866069,-12.76792565458307],[28.09884670129139,-12.77154488362985],[28.09820634075841,-12.77491554189099],[28.09744691911295,-12.77802496821919],[28.09664546753287,-12.78098487061571],[28.09583117638021,-12.78381826135393],[28.09506748001998,-12.78664106590416],[28.09433792563442,-12.78967617911158],[28.09361236984402,-12.79267130143205],[28.09292133585748,-12.79551270588752],[28.09218787253939,-12.79822971356624],[28.09145099181093,-12.80086772957042],[28.09073133556129,-12.80326224257254],[28.0899536329777,-12.80556727265891],[28.08904776030321,-12.80790247085956],[28.08796878861311,-12.81055343002277],[28.08704272716074,-12.81328844152582],[28.08623572003451,-12.81597580901436],[28.08560001843172,-12.81867627098168],[28.08512591286723,-12.82123819770476],[28.08471543638154,-12.82384938968928],[28.08425874852546,-12.82679294781535],[28.08374312388764,-12.82949427417818],[28.08323322766018,-12.83202164467115],[28.08267777489684,-12.83455924186263],[28.08217344688747,-12.83693644612224],[28.08167254777418,-12.83938125748388],[28.08118342949371,-12.84200051650003],[28.08054195857526,-12.84484268567501],[28.08000739947655,-12.84721115998749],[28.07956193356096,-12.84918488858123],[28.07919071196464,-12.85082966240934],[28.07888136063437,-12.8522003072661],[28.07862356785914,-12.85334251131341],[28.07733460398302,-12.85905353154991],[28.07430454192961,-12.85896690813451],[28.07118640905668,-12.85891519866745],[28.06824453933537,-12.85902380976954],[28.06548821222131,-12.85929834528767],[28.06278456623197,-12.85974817620174],[28.06012926110743,-12.86041661614111],[28.05765721470886,-12.86113462156337],[28.0551841474908,-12.86203818040195],[28.0524624725847,-12.86334772932424],[28.0496477364418,-12.8647772891455],[28.04665578498463,-12.86649243557748],[28.04385774331388,-12.86793173135914],[28.0409695152413,-12.86906106812762],[28.03798545080196,-12.87004239985766],[28.03476657853115,-12.87104374759722],[28.03171949468247,-12.87211799044135],[28.02859911499897,-12.87343256523842],[28.02553585139648,-12.87488755449546],[28.02253434310512,-12.87640714003183],[28.01952149217438,-12.87766689676772],[28.01599554545219,-12.87870737331227],[28.01221551538323,-12.87974959147273],[28.00839838727655,-12.88092186380732],[28.00492627823873,-12.88208647492352],[28.00162695544844,-12.88334357971555],[27.99819870188001,-12.88486365015975],[27.99473220420566,-12.88604352811354],[27.99132086125337,-12.88700214032127],[27.9877260747482,-12.88796615456524],[27.98323396016703,-12.8891037911664],[27.97912324971235,-12.89030600521128],[27.9750567861602,-12.89175424043556],[27.97143216308365,-12.89296511808926],[27.96804020982671,-12.89400814562066],[27.96452650506929,-12.8949534219415],[27.9611101615925,-12.89575973457863],[27.95787452955433,-12.89645664099811],[27.95462756441627,-12.89698634941948],[27.95157393328287,-12.89736692169174],[27.94868930247027,-12.89756236242753],[27.94568500450576,-12.89754319218813],[27.94278455498493,-12.89745017571149],[27.93991857263103,-12.89740326222466],[27.93678154309728,-12.89745548106006],[27.93355389841332,-12.8976591886903],[27.93041994998147,-12.89777329496243],[27.92748170135857,-12.89787560553779],[27.92466490387999,-12.89800186497302],[27.92192284914013,-12.89802065543858],[27.91912744989616,-12.89797589322543],[27.91627809468445,-12.89793368074752],[27.91340935791152,-12.89792323268924],[27.91076963631655,-12.89792343589248],[27.90828639562188,-12.8979800241427],[27.9056743692837,-12.89814266253486],[27.9031000536005,-12.89844322859791],[27.90050439655732,-12.89875826224194],[27.8975320867469,-12.8990674928469],[27.89466691818716,-12.89932798946575],[27.89154179896148,-12.8995678750941],[27.8884994963613,-12.89979679317128],[27.88553296712801,-12.89995235019522],[27.88262611686633,-12.90007338268735],[27.87941954901273,-12.90018500876106],[27.87638710545996,-12.90023067202293],[27.87337535011559,-12.9002738977754],[27.87045243935485,-12.90030977164434],[27.86740112256781,-12.90034811999003],[27.86420200100628,-12.90048983995264],[27.86062240258938,-12.90063345214949],[27.8572521033315,-12.90074446394081],[27.85367695512343,-12.90081548836413],[27.85014937088009,-12.90088180253863],[27.84679495895435,-12.90080837876618],[27.84368714279452,-12.9006792228384],[27.84089333088512,-12.90054708109527],[27.83825634534838,-12.9004535077249],[27.83557676873823,-12.90045348642326],[27.83258725188879,-12.90062638544138],[27.82987865756452,-12.90080276132731],[27.82722322906747,-12.9009957737885],[27.82472512150269,-12.90113183742414],[27.82208567606201,-12.90119923435338],[27.8193100517743,-12.9012015496537],[27.81629923783567,-12.90127264643915],[27.81358936512591,-12.90136832920155],[27.81109354033083,-12.90146806603267],[27.80864187084978,-12.90160483016792],[27.80591795313258,-12.90182704642612],[27.80319774912585,-12.90191207888201],[27.80029421514367,-12.90187132560009],[27.79757554724176,-12.90186721480619],[27.79506407201382,-12.90190112626297],[27.79255056943049,-12.90196506405182],[27.78961982669652,-12.90208644153634],[27.78655665061564,-12.90230163937282],[27.783464843815,-12.90245829990183],[27.78046618519356,-12.90253748851593],[27.77748998009077,-12.90239603454259],[27.77458187058239,-12.90218408733401],[27.77159324697553,-12.90190734033598],[27.76832040594986,-12.90139994313486],[27.76535067784364,-12.90055622276564],[27.76285944293882,-12.89945078470363],[27.76081082187377,-12.89785216147859],[27.7593289361233,-12.89604427822668],[27.75851246331792,-12.89367921703304],[27.75777102610216,-12.89059809989344],[27.75695204981182,-12.88757897802799],[27.75622892129135,-12.88484453065613],[27.75561361191257,-12.88223096123771],[27.75506565177241,-12.87967512244617],[27.75465277330632,-12.87719282115075],[27.75424257002121,-12.87481296323229],[27.75375590343246,-12.87224548479879],[27.75305674968191,-12.86904711231745],[27.7523997889207,-12.86620457993023],[27.75169595504599,-12.86356599244597],[27.75082159842613,-12.86088311453466],[27.74994421916219,-12.85829101053338],[27.74898388822041,-12.85578277202238],[27.74780755579088,-12.85315974094474],[27.74674438967658,-12.85057744127614],[27.74567840790282,-12.84770624220118],[27.74442790579452,-12.84481700583314],[27.74291132662751,-12.84190314307726],[27.74130873978421,-12.83901954004699],[27.73931038602015,-12.83583428802691],[27.7373594446547,-12.83292125380903],[27.73553505890919,-12.83001912999285],[27.73375109048354,-12.82687671094499],[27.73239439936657,-12.82376509845341],[27.73154251401386,-12.82047147198324],[27.73110195115867,-12.81738295682511],[27.731143856393,-12.81423608230948],[27.73151268608407,-12.81139532790795],[27.73221463256035,-12.80860005701167],[27.73350696224825,-12.80543114804605],[27.7348751473433,-12.80142601007656],[27.73582029600976,-12.797456016396],[27.73664020278746,-12.79325051789869],[27.73767954438734,-12.78913364005106],[27.7387162349956,-12.78533699520006],[27.7398607755494,-12.78149110998277],[27.74084613277567,-12.7778954925726],[27.74164340701113,-12.77420472225523],[27.74230869992768,-12.77076816117321],[27.74293451098091,-12.76735229716943],[27.74362306944451,-12.7639323982812],[27.74416571996613,-12.76067890623624],[27.74468082710751,-12.7575973006786],[27.74514936917716,-12.75477534818445],[27.74560556933271,-12.75218841302594],[27.74608507453526,-12.74966949241378],[27.74652516218516,-12.74712137557769],[27.74696510286756,-12.74418917600753],[27.74749865165917,-12.74133530565686],[27.74807384633434,-12.73859464941152],[27.74872085502522,-12.73564430999792],[27.74919661956013,-12.73233355254393],[27.74954661205152,-12.72846054889125],[27.74979779705677,-12.72510864677442],[27.74995945828123,-12.72211690748899],[27.75000401860806,-12.71929205398154],[27.74993862777027,-12.71653246055803],[27.74968651225653,-12.71344241930159],[27.74930642988851,-12.70969942042451],[27.74867406510993,-12.70616191474834],[27.74766126630687,-12.70253507749979],[27.74656477994968,-12.69899912980121],[27.7455345877763,-12.69523776315885],[27.74460946302728,-12.69173740134049],[27.74380966493334,-12.68851921026366],[27.74309356701682,-12.68548080025912],[27.7424156649919,-12.68230212943563],[27.7416884391155,-12.67912718675324],[27.74081168376092,-12.67567380979137],[27.73983405924381,-12.67169714982021],[27.73850974253406,-12.66652981576843],[27.73740614527593,-12.66222370405862],[27.73648648089416,-12.65863527763378],[27.73572009390935,-12.65564492227974],[27.73508143808868,-12.65315295948471],[27.73454922490478,-12.65107632382219],[27.73188815898529,-12.64069314550956]]],"type":"Polygon"}
}

Create GeoJSON I/O project using new Sytem.Text.Json

Resolving #42 it seemed worthwhile to create a NetTopologySuite.IO project that does not depend on Newtonsoft.Json but on the new System.Text.Json package to improve performance and avoid/minimize unnecessary package references.

Add an extra overload of JsonSerializer.CreateDefault()

It would be useful to have an overload of the CreateDefault static method that accepts the JsonSerializerSettings as parameter. It is a method that exists on the JsonSerializer but is missing on the GeoJsonSerializer.

The code would be something like this:

public new static JsonSerializer CreateDefault(JsonSerializerSettings settings)
{
    var s = JsonSerializer.CreateDefault(settings);
       
    AddGeoJsonConverters(s, GeometryFactory.Default);
    return s;
}

GeoJsonSerializer.Deserialize<Coordinate> return null

Hello!
I try write Coordinate to json and than read it back to object.

var geoSerializer = GeoJsonSerializer.CreateDefault();

var c1 = new Coordinate(1, 2);
var sb = new StringBuilder();
geoSerializer.Serialize(new JsonTextWriter(new StringWriter(sb)), c1);
var json = sb.ToString(); // it is equal to "[1.0,2.0]"

var c2 = geoSerializer.Deserialize<Coordinate>(new JsonTextReader(new StringReader(json)));

As we can see json is correct, but after Deserialize I got null.

I assume, that CoordinateConverter which sit inside GeoJsonSerializer should do both write and read conversion, but it doesn't. It is issue or correct behavior?

I use 1.15.3 version of NetTopologySuite and NetTopologySuite.IO.GeoJSON.

MissingMethodException: Method not found: 'GeoAPI.Geometries.ILinearRing GeoAPI.Geometries.IGeometryFactory.CreateLinearRing()'

From NetTopologySuite #243 original poster: @nkovacic:

I am using NetTopologySuite to load a GeoJson using the NetTopologySuite.IO.GeoJSON package.
The issue appears when I try to read a FeatureCollection GeoJson.

[Route("api/v1/test")]
public class TestController : BaseApiServiceController
{
    public IHostingEnvironment Env { get; set; }

    [Route("geo")]
    public async Task<IActionResult> TestTopology()
    {
        var country = "si";
        var basePath = $"{Env.ContentRootPath}/App_Data/geo/{country}/regions.geojson";

        using (var fileStream = new FileStream(basePath, FileMode.Open))
        using (var reader = new StreamReader(fileStream))
        {
            var geoJsonText = await reader.ReadToEndAsync();
            var geoJsonReader = new GeoJsonReader();
            var featureCollection = geoJsonReader.Read<FeatureCollection>(geoJsonText);

            return Ok(new { numberOfFeatures = featureCollection.Features.Count });
        }
    }
}

The geoJsonReader.Read<FeatureCollection> part returns the following error:

MissingMethodException: Method not found: 'GeoAPI.Geometries.ILinearRing GeoAPI.Geometries.IGeometryFactory.CreateLinearRing()'.
NetTopologySuite.Geometries.Polygon..ctor(ILinearRing shell, ILinearRing[] holes, IGeometryFactory factory)
NetTopologySuite.Geometries.GeometryFactory.CreatePolygon(ILinearRing shell, ILinearRing[] holes) in GeometryFactory.cs
NetTopologySuite.IO.Converters.GeometryConverter.ParseGeometry(JsonReader reader, JsonSerializer serializer) in GeometryConverter.cs
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object existingValue)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent)
Newtonsoft.Json.JsonSerializer.Deserialize<T>(JsonReader reader)
NetTopologySuite.IO.Converters.FeatureConverter.ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) in FeatureConverter.cs
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object existingValue)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent)
Newtonsoft.Json.JsonSerializer.Deserialize<T>(JsonReader reader)
NetTopologySuite.IO.Converters.FeatureCollectionConverter.ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) in FeatureCollectionConverter.cs
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object existingValue)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent)
Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
Newtonsoft.Json.JsonSerializer.Deserialize<T>(JsonReader reader)
NetTopologySuite.IO.GeoJsonReader.Read<TObject>(string json) in GeoJsonReader.cs

I am using the project in a ASP.NET Core 2 Web Api project targeting .net standard 2,
NetTopologySuite version is 1.15.0-pre063.

After quick debugging your source code it appears that Polygon constructor is calling an old method in IGeometryFactory which is not available in the prerelease version.

GeoJsonReader to support Stream

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of NetTopologySuite
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

Currently the only input the Read method supports is string. It would be great if this method also supported a stream. This would be useful for large datasets and memory management.

[Question/Bug] NetTopologySuite.IO.GeoJson in combination with EntityFrameworkCore.SqlServer.NetTopologySuite

I'm trying to use SQLServer to search and process geographical data in the backend side and need to import some data from GeoJSON.
when including both libs NetTopologySuite.IO.GeoJson 1.7.5 and EntityFrameworkCore.SqlServer.NetTopologySuite 2.2.6 the following error appear when trying to resolve the DbContext

System.MissingMethodException: 'Method not found: 'GeoAPI.IGeometryServices NetTopologySuite.NtsGeometryServices.get_Instance()'.'

after thinkering a bit with it and searching what that issue might be I found out that the problem occurs when one dependency is installed on the project that being NetTopologySuite

Is there a way to make them work together?

<ItemGroup>
    <PackageReference Include = "GeoAPI" Version="1.7.5" />
    <PackageReference Include = "Microsoft.EntityFrameworkCore" Version="2.2.6" />
    <PackageReference Include = "Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite" Version="2.2.6" />
    <PackageReference Include = "NetTopologySuite.Core" Version="1.15.3" />
    <PackageReference Include = "NetTopologySuite" Version="2.0.0" /> //<-- adding this package will result in the exception being thrown
</ItemGroup>
using GeoAPI.Geometries;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;


namespace script
{
    class Program
    {
        public static string connectionString = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=[database]; Integrated Security=True;";

        public static IConfigurationRoot Configuration { get; private set; }

        static void Main(string[] args)
        {
            IServiceProvider provider = ConfigureServices(new ServiceCollection());

            var x = provider.GetService<Db>(); //will throw exception when NetTopologySuite is added to the project
        }


        public static IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<Db>(_ => new Db(new DbContextOptionsBuilder().UseSqlServer(connectionString, x => x.UseNetTopologySuite()).Options));
            services.AddSingleton<IGeometryFactory>(_ => GeoAPI.GeometryServiceProvider.Instance.CreateGeometryFactory(4326));

            return services.BuildServiceProvider();
        }
    }

    public class GeoRecord
    {
        public Guid Id { get; set; }

        public IGeometry Geometry { get; set; }
    }

    public class Db : DbContext
    {
        public Db(DbContextOptions options) : base(options) //exception will be thrown here when trying to resolve Db dependency
        {
        }

        public DbSet<GeoRecord> GeoRecords { get; set; }
    }
}

GeoJsonWriter.Write fails if first Feature of FeatureCollection has null Geometry

Calling Write(FeatureCollection featureCollection) results in a NullReferenceException being thrown, if the Geometry property of the first Feature is null.

If the first Feature has valid Geometry and the second Feature has null Geometry, no exception is thrown.

Here's a unit test to demonstrate the issue (with xUnit, FluentAssertions):

[Fact]
public void WriteFeatureCollection_ThrowsIfNullFirst_NotThrowIfNotNullFirst()
{
    // Setup
    var geoJsonWriter = new GeoJsonWriter();
    
    var featureJson = "{\"type\": \"Feature\",\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[0,0],[2,2],[3,2]]},\"properties\": {\"key\": \"value\"}}";
    var notNullGeometryFeature = new GeoJsonReader().Read<Feature>(featureJson);
    
    var attributesTable = new AttributesTable {{"key", "value"}};
    IGeometry geometry = null;
    var nullGeometryFeature = new Feature(geometry, attributesTable);
    
    var features_notNullFirst = new Collection<IFeature>
    {
        notNullGeometryFeature,
        nullGeometryFeature
    };
    
    var features_nullFirst = new Collection<IFeature>
    {
        nullGeometryFeature,
        notNullGeometryFeature
    };
    
    var featureCollection_notNullFirst = new FeatureCollection(features_notNullFirst);
    var featureCollection_nullFirst = new FeatureCollection(features_nullFirst);
    
    // Act
    Action write_notNullFirst = () => geoJsonWriter.Write(featureCollection_notNullFirst);
    Action write_nullFirst = () => geoJsonWriter.Write(featureCollection_nullFirst);
    
    // Assert
    write_notNullFirst.Should().NotThrow<NullReferenceException>();
    write_nullFirst.Should().Throw<NullReferenceException>();
}

GeoJsonWriter.Write fails with empty FeatureCollection

When calling Write(FeatureCollection featureCollection) with an empty FeatureCollection, an ArgumentOutOfRangeException is thrown.

var writer = new GeoJsonWriter();
var json = writer.Write(new FeatureCollection());

This throws the following:
System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

allow deserialization of null geometry

I have problem with deserializing nullable Point object.
For example I have class

class Foo
{
      public Point {get; set;} // it can be null
}

when I Foo b = serializer.Deserialize<Foo>(reader); I get exception:
Newtonsoft.Json.JsonReaderException: 'Expected Start object '{' Token'

I think this is bug. But as I see this bug was fixed in e6aed6c, if it is true when this changes will be avalaible?

runtime: .net core 2.2
NetTopologySuite.IO.GeoJSON 1.15.0
Newtonsoft.Json 12.0.1

GeoJSON parser fails to parse properties

From @dmytro-gokun on March 27, 2018 14:52

Hi,

i have this piece of GeoJSON:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      12.5851472,
      55.68323837
    ]
  },
  "crs": {
    "type": "name",
    "properties": {
      "name": "EPSG:4326"
    }
  },
  "properties": {
    "id": "0a3f507a-b2e6-32b8-e044-0003ba298018",
    "status": 1,
    "vejkode": "4112",
    "vejnavn": "Landgreven",
    "adresseringsvejnavn": "Landgreven",
    "husnr": "10",
    "supplerendebynavn": null,
    "postnr": "1301",
    "postnrnavn": "Kรธbenhavn K",
    "kommunekode": "0101"
  }
}

I use this code to parse it:

var feature = new GeoJsonReader().Read<Feature>(json);

The resulting "feature" object contains just 1 element in it's "Attributes" property. One named "name" with value of "EPSG:4326". Instead, I expect it to contain "id", "status", "vejkode" and so on. Obviously, the parser is fooled by "properties" nested inside of "crs".

Thanks in advance,
Dmytro.

Copied from original issue: NetTopologySuite/NetTopologySuite#224

Trouble serializing valid GeoJSON with "properties" field

Hello, I am having a problem with the final GeoJSON structure after serializing an object.
Psuedocode for the model:

public class Country
{
     public string ID {get; set;}
     public int Name{get; set;}
     public Geometry Geometry {get; set;}
}        

Psuedo-code for the controller:

public IActionResult ExampleGeoJSON()
{
    
    Country country = countriesRepo.GetCountryFromDatabaseByID("AA");
   //
    
    string geoJson;
    var serializer = GeoJsonSerializer.Create();
    using (var stringWriter = new StringWriter())
    using (var jsonWriter = new JsonTextWriter(stringWriter))
    {
        serializer.Serialize(jsonWriter, country);
        geoJson = stringWriter.ToString();
    }
    
    return this.Content(geoJson, "application/json");
}

The returned JSON looks like this:

{"ID":"1","Name":"AA","Geometry":{"type":"Point","coordinates":[1.2,1.2]}}

As we can see, the geometry is coming through perfectly and as expected, but

  1. There is no "type" field for the geoJSON.
  2. there is no "properties" field. In order to be a valid GeoJSON, the json should be structured like this:
{"type": "Feature","Geometry":{"type":"Point","coordinates":[1.2,1.2]}, "Properties":{"ID":"1","Name":"AA"}}

Is this functioning as intended, is there something I've missed/ an option for this? Or is this something I have to write myself?

GeoJSON feature ID is lost in parsing when feature has no properties

From @dalbani on March 2, 2018 15:35

As far as I understand, given that FeatureConverter relies on the Attributes property of a Feature to store its ID, the value is ignored during parsing when no properties where present in the original GeoJSON.
Example:

{
  "id": "featureID",
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [42, 42]
  }
  // no "properties" here!!
}

In this case, AFAIK, there's no way to retrieve the original ID from the deserialized Feature object, because Attributes is null and has not been filled in with the ID.

Tested with latest 1.15-pre version, with .NET Core 2.0.

I see that an issue was opened in 2016 about GeoJSON feature IDs: NetTopologySuite/NetTopologySuite#83.
A workaround was given, but it doesn't work in the case I mention here.

I suppose a fix would be to always create an empty AttributesTable โ€” but then you lose the ability to determine if no properties were present in the original GeoJSON.

Compared to other implementations of GeoJSON parses, the use of the Attributes property to store the ID looks like a hack.
Wouldn't it be possible to have a dedicated property in the Feature class??

Copied from original issue: NetTopologySuite/NetTopologySuite#216

How serialize FeatureCollection with Multilinestring and Z coordinate?

I created FeatureCollection with geometry Multilinestring and wrote her to JSON string. In geometry, I have Z coordinate.

GeoJsonWriter writer = new GeoJsonWriter();
var geoJson = writer.Write(mycollection);

It's ok. I get string GeoJSON, but without Z coordinate.
" "coordinates": [
[
[
1263.1974032828948,
11930.429698849097
],
[
1264.6275812591848,
11917.549948748201
],
[
1368.966530531652,
11924.469217129983
],"

Why and how to add Z?

NetTopologySuite.IO.GeoJson NU1602 NuGet Warning

From @dfaivre on April 4, 2018 20:55

Description

I get NU1602 (NuGet) warning on compile: Warning NU1602 NetTopologySuite.IO.GeoJSON 1.14.0 does not provide an inclusive lower bound for dependency Newtonsoft.Json. An approximate best match of Newtonsoft.Json 3.5.8 was resolved

I'd be happy to help contribute a fix for this. Also, should I be posting this issue here (https://github.com/NetTopologySuite/NetTopologySuite.IO.GeoJSON)?

Steps to Reproduce

  • Reference NetTopologySuite.IO.GeoJSON 1.14.0
  • Build
  • Check Warnings

image

System Configuration

Tell us about the environment where you are experiencing the bug:

  • NetTopologySuite version: 1.14.0
  • Other NetTopologySuite packages and versions:
  • Environment (Operating system, version and so on): Windows, Visual Studio 2017 (+Resharper 2017.3)
  • .NET Framework version: 4.7
  • Additional information:

Copied from original issue: NetTopologySuite/NetTopologySuite#225

Json.NET: Reader tries to read too much when "coordinates" is null

var token = JToken.Parse("{\"type\":\"LineString\",\"coordinates\":null}");
var lineString = token.ToObject<LineString>(GeoJsonSerializer.CreateDefault());

In this situation, we will get EndOfStreamException.

The issue is that this code doesn't consider the possibility that we might be on a null token:

case "coordinates":
reader.ReadOrThrow(); //read past start array tag
coords = ReadCoordinates(reader);
break;

As it turns out, 4STJ actually does write out null to signal an empty geometry, as shown in the longer repro below, which effectively means that the Json.NET version doesn't interoperate properly with the 4STJ version ๐Ÿ˜ž:

var stjOptions = new System.Text.Json.JsonSerializerOptions
{
    Converters = { new NetTopologySuite.IO.Converters.GeoJsonConverterFactory() },
};

var seq = GeometryFactory.Default.CoordinateSequenceFactory.Create(0, 2);
var lineString = GeometryFactory.Default.CreateLineString(seq);
string s = System.Text.Json.JsonSerializer.Serialize(lineString, stjOptions);

var jsonNetSerializer = NetTopologySuite.IO.GeoJsonSerializer.CreateDefault();
var jsonNetToken = Newtonsoft.Json.Linq.JToken.Parse(s);
var roundTrip = jsonNetToken.ToObject<LineString>(jsonNetSerializer);

STJ: Give callers access to the original JsonElement of our IAttributesTable

TryDeserializeJsonObject<T> / TryGetJsonObjectPropertyValue<T> are great, but some advanced use cases would really just love to have the JsonElement to do whatever they want to it.

For example, consider OpenStreetMap: this is an example of geometric data with highly unstructured data associated with each entity.

  • If I store tags as properties in a UTF-8 collated varchar(max) column in a SQL Server 2019 database, I could query them using the database's built-in JSON features.
  • I would still want to map to JsonElement on my EF Core entities.
  • If I want to load from a GeoJSON extract of the data, then I need a JsonElement that represents the IAttributeTable.

The easiest way to do that would be to just return the JsonElement that we already have ๐Ÿ˜€.

4STJ: Errors when trying to deserialize IFeature with nulls

If either a GeoJSON Feature's "geometry" or "bbox" property is null, our converter will read the wrong amount of data.

Repro below... I'll push a fix when I'm done with work today.

ConsoleApp0.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="NetTopologySuite.IO.GeoJSON4STJ" Version="2.0.4" />
  </ItemGroup>

</Project>

Program.cs

using System;
using System.Text.Json;

using NetTopologySuite.Features;
using NetTopologySuite.IO.Converters;

static class Program
{
    static void Main()
    {
        const string JsonFeature1 = "{ \"type\": \"Feature\", \"geometry\": null }";
        const string JsonFeature2 = "{ \"type\": \"Feature\", \"bbox\": null }";

        var options = new JsonSerializerOptions
        {
            Converters = { new GeoJsonConverterFactory() },
        };

        try
        {
            JsonSerializer.Deserialize<IFeature>(JsonFeature1, options);
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
            Console.Error.WriteLine();
            Console.Error.WriteLine();
        }

        try
        {
            JsonSerializer.Deserialize<IFeature>(JsonFeature2, options);
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
            Console.Error.WriteLine();
            Console.Error.WriteLine();
        }
    }
}

Output:

System.Text.Json.JsonException: Expected token is 'EndObject' but was 'Null' (Value '').
   at NetTopologySuite.IO.Converters.Utility.ThrowForUnexpectedToken(JsonTokenType requiredNextTokenType, Utf8JsonReader& reader)
   at NetTopologySuite.IO.Converters.StjFeatureConverter.Read(Utf8JsonReader& reader, Type objectType, JsonSerializerOptions options)
   at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
   at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader)
   at System.Text.Json.JsonSerializer.Deserialize(String json, Type returnType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at Program.Main() in C:\...\Program.cs:line 21


System.Text.Json.JsonException: The converter 'NetTopologySuite.IO.Converters.StjFeatureConverter' read too much or not enough. Path: $ | LineNumber: 0 | BytePositionInLine: 33.
   at System.Text.Json.ThrowHelper.ThrowJsonException_SerializationConverterRead(JsonConverter converter)
   at System.Text.Json.JsonPropertyInfo.VerifyRead(JsonTokenType tokenType, Int32 depth, Int64 bytesConsumed, Utf8JsonReader& reader)
   at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
   at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader)
   at System.Text.Json.JsonSerializer.Deserialize(String json, Type returnType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at Program.Main() in C:\...\Program.cs:line 32

Serializer ignores the IPrecisionModel of geometries

When serializing a geometry, the serializer seems to ignore the IPrecisionModel of the IGeometry. The coordinates in the JSON are not formatted according to the precision model, but are outputted as is.

Example:

var coords = new []
{
    new Coordinate(0.001, 0.001),
    new Coordinate(10.1, 0.002),
    new Coordinate(10, 10.1),
    new Coordinate(0.05, 9.999),
    new Coordinate(0.001, 0.001)
};

// Creating the polygon with PrecisionModels.Fixed
var polygon = GeometryFactory.Fixed.CreatePolygon(coords);

var serializer = GeoJsonSerializer.CreateDefault();
var writer = new StringWriter();
serializer.Serialize(writer, polygon);

var str = polygon.ToString();
// The precision is one decimal place as expected
// POLYGON ((0 0, 10.1 0, 10 10.1, 0.1 10, 0 0))

var json = writer.ToString();
// The precision is ignored
// {"type":"Polygon","coordinates":[[[0.001,0.001],[10.1,0.002],[10.0,10.1],[0.05,9.999],[0.001,0.001]]]}

Version: 1.15.2

PrecisionModel not applying correctly to BoundingBox

Issue

When outputting a Feature or FeatureCollection the PrecisionModel is not correctly applied to the BoundingBox (bbox) value. It seems that it is applied correctly on the X-axis but not on the Y-axis.

Relevant code

namespace Application
{
    public class Startup
    {
        private const int OutputPrecision = 1000000;

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRouting(options => options.LowercaseUrls = true);
            services.AddControllers(options =>
                {
                    // Prevent the following exception: 'This method does not support GeometryCollection arguments' 
                    // See: https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/585 
                    options.ModelMetadataDetailsProviders.Add(
                        new SuppressChildValidationMetadataProvider(typeof(Point)));
                    options.ModelMetadataDetailsProviders.Add(
                        new SuppressChildValidationMetadataProvider(typeof(Coordinate)));
                    options.ModelMetadataDetailsProviders.Add(
                        new SuppressChildValidationMetadataProvider(typeof(LineString)));
                    options.ModelMetadataDetailsProviders.Add(
                        new SuppressChildValidationMetadataProvider(typeof(MultiLineString)));
                })
                .AddNewtonsoftJson(options =>
                {
                    options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;

                    foreach (var converter in GeoJsonSerializer
                        .Create(new GeometryFactory(new PrecisionModel(OutputPrecision), 4326)).Converters)
                    {
                        options.SerializerSettings.Converters.Add(converter);
                    }
                });
        }
    }
}

Current output

I have shortened the LineString value as it's irrelevant.

{
	"type": "FeatureCollection",
	"features": [{
		"type": "Feature",
		"bbox": [-72.331475, 41.29594540929457, -72.277123, 41.611117942006175],
		"geometry": {
			"type": "LineString",
			"coordinates": [
				[-72.316099, 41.295945],
				[-72.316452, 41.296307],
				[-72.317182, 41.296954],
				[-72.317813, 41.297589],
				[-72.31811, 41.297928]
			]
		},
		"properties": {
			"cumulativeDistance": 42.3458,
			"distance": 42.3458,
			"cumulativeTime": 42.3458,
			"time": 42.3458
		}
	}],
	"bbox": [-72.331475, 41.29594540929457, -72.277123, 41.611117942006175]
}

Expected output

I have shortened the LineString value as it's irrelevant.

{
	"type": "FeatureCollection",
	"features": [{
		"type": "Feature",
		"bbox": [-72.331475, 41.295945, -72.277123, 41.611117],
		"geometry": {
			"type": "LineString",
			"coordinates": [
				[-72.316099, 41.295945],
				[-72.316452, 41.296307],
				[-72.317182, 41.296954],
				[-72.317813, 41.297589],
				[-72.31811, 41.297928]
			]
		},
		"properties": {
			"cumulativeDistance": 42.3458,
			"distance": 42.3458,
			"cumulativeTime": 42.3458,
			"time": 42.3458
		}
	}],
	"bbox": [-72.331475, 41.295945, -72.277123, 41.611117]
}

Weird behaviour when writing geometry array.

When writing a geometry there is some strange unexpected behaviour:

            var lineStringArray = new []
                            { 
                                new LineString(
                                    new []
                                    {
                                        new Coordinate(3.216290473937988, 51.21516381557017),
                                        new Coordinate(3.220260143280029, 51.21813418800571),
                                        new Coordinate(3.221204280853271, 51.21521757967015),
                                        new Coordinate(3.221611976623535, 51.21420949234874)
                                    })
                            };
            
            var serializer = NetTopologySuite.IO.GeoJsonSerializer.Create();

            // first case: writes a proper linestring geometry.
            var stringWriter = new StringWriter();
            serializer.Serialize(stringWriter, lineStringArray[0]);
            var json = stringWriter.ToString();
            
            // second case: writes a geometries=[] array (!)
            stringWriter = new StringWriter();
            serializer.Serialize(stringWriter, lineStringArray);
            json = stringWriter.ToString();           

The first case gives a proper linestring:

{"type":"LineString","coordinates":[[3.2162904739379878,51.215163815570172],[3.2202601432800289,51.218134188005713],[3.221204280853271,51.215217579670153],[3.2216119766235352,51.214209492348743]]}

The second case does this:

"geometries":[{"type":"LineString","coordinates":[[3.2162904739379878,51.215163815570172],[3.2202601432800289,51.218134188005713],[3.221204280853271,51.215217579670153],[3.2216119766235352,51.214209492348743]]}]

Expected would be a geometry array as follows:

[{"type":"LineString","coordinates":[[3.2162904739379878,51.215163815570172],[3.2202601432800289,51.218134188005713],[3.221204280853271,51.215217579670153],[3.2216119766235352,51.214209492348743]]}]

Release a version compatible with .NET Core 3.0 preview 7

The latest version of .NET Core 3.0, and more specifically Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite now depends on the latest NetTopologySuite 2.0.0-pre001 package. This version no longer depends on GeoAPI.NET: geometry types are now an integral part of the NetTopologySuite API.
This library, which acts on GeoAPI.NET instances, can no longer work in this environment. And so it seems to me that it needs some love right now.

I might be able to contribute on this one. I would probably need quite some guidance though.

Look into adding appropriate support for OpenAPI

As a developer of a web API that uses GeoJSON-formatted inputs and outputs, I want a library maintained by the NetTopologySuite organization that I can use to document the GeoJSON parts of my API (e.g., via Swashbuckle.AspNetCore.SwaggerGen) so that I don't have to understand and recreate the details of the GeoJSON format in my OpenAPI schemas.

This can and should be independent of Json.NET vs. System.Text.Json, since (from my understanding) this has more to do with the format of the data rather than the actual code that produces / consumes it.

As one possible idea, if I had an instance of type NetTopologySuite.Geometries.Polygon that represents an example input to an API, I would like to give it to something from NTS and get back an instance of type Microsoft.OpenApi.Models.OpenApiSchema that represents a GeoJSON Polygon's schema, and has the .Example property filled out with the example data that I gave it.

System.TypeLoadException: Could not load type 'NetTopologySuite.CoordinateSystems.ICRSObject'

Hi

Following @airbreather 's suggestions in #38, I m using Ef Core 2.2.6 so I use NetTopologySuite 1.15.3 as suggested, I m able to migrate the DataBase with GeoometryPoint ๐Ÿ‘

From what I understand, if I want to deserialize the json containing Spatial data, I need to use NetTopologySuite.IO.GeoJSON. I looked in the dependencies, the last available version of NetTopologySuite.IO.GeoJSON using NetTopologySuite (without .Core) is 1.14.0.

In my code, I do:

using (var geoBaseReader = new JsonTextReader(File.OpenText(GeoBaseFilename)))
{
   var officialGeoBase = new GeoJsonSerializer().Deserialize<GeoBaseClass>(geoBaseReader);
}

When I launch the execution, I have this error:

System.TypeLoadException: Could not load type 'NetTopologySuite.CoordinateSystems.ICRSObject'

What did I misconfigure?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.