nettopologysuite / nettopologysuite.io.geojson Goto Github PK
View Code? Open in Web Editor NEWGeoJSON IO module for NTS.
License: BSD 3-Clause "New" or "Revised" License
GeoJSON IO module for NTS.
License: BSD 3-Clause "New" or "Revised" License
It appears that Microsoft has decided to create its own Json library focused on perfomance.
Can be seen here:
dotnet/announcements#90
aspnet/Announcements#325
I know that Json.Net is still supported but I was wondering if the new Json will be supported by this library?
In any case, the wiki page should be updated since there were breaking changes introduced in 3.0.
If I manage to make it work using this SO question I'll update the wiki.
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...
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
}
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
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?
We have a dependency on the CoordinateConverter to create a custom JsonSerializerSettings. We were attempting to upgrade to the latest patch version but now our code breaks because the constructors for CoordinateConverter were made internal. Does this package follow SemVer?
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.
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?
//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.
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?
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 ''.
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)
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);
}
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.
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));
}
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...
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
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.
How can I Use NetTopologySuite.IO.GeoJSON to return GeoJson formated response from asp.net core API end point?
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.
So instead of GeometryFactory.Default
use new GeometryFactory(new PrecisionModel(), 4326)
.
Regards,
Jochen
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
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();
}
}
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
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"}
}
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.
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;
}
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.
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.
DEBUG
and RELEASE
modeCurrently 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.
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; }
}
}
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>();
}
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
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
Is this repo meant to replace https://github.com/NetTopologySuite/NetTopologySuite/tree/develop/NetTopologySuite.IO/NetTopologySuite.IO.GeoJSON ?
If so, how come changes were done in the original repo, but not here?
Which repo is https://www.nuget.org/packages/NetTopologySuite.IO.GeoJSON/ built from?
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
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
{"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?
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
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?
I need to convert the GeoJSON to PBF vector tiles. Is there any way to do that?
Since creating this repository and now there have been considerable changes in the develop branch:
From @dfaivre on April 4, 2018 20:55
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)?
Tell us about the environment where you are experiencing the bug:
Copied from original issue: NetTopologySuite/NetTopologySuite#225
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:
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);
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.
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.JsonElement
on my EF Core entities.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 ๐.
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.
<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>
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();
}
}
}
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
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
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.
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);
}
});
}
}
}
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]
}
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]
}
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]]}]
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.
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.
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.