Geomatys / geotoolkit

Geotoolkit.org (abridged Geotk) is a free software, Java language library for developing geospatial applications. The library can be used for desktop or server applications. Geotk is built on top of Apache SIS and is used as a laboratory for the later.
http://www.geotoolkit.org/
53 stars 28 forks source link

[geojson-feature] Parser does not accept valid geoJson #13

Closed jmbourdaret closed 2 years ago

jmbourdaret commented 3 years ago

Not sure about that, but a geoJson with "type" after the "coordinates" should still be valid in my opinion It is not always easy to control properties ordering in a json.

@Test
void parsingOrderBugTest() throws IOException {
    String geoJsonPolygonString = "" +
            "         {\n" +
            "           \"coordinates\": [\n" +
            "             [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],\n" +
            "               [100.0, 1.0], [100.0, 0.0] ]\n" +
            "             ]\n" +
            "           \"type\": \"Polygon\"\n" +
            "         }" ;
    GeoJSONObject obj = GeoJSONParser.parse(new ByteArrayInputStream( geoJsonPolygonString.getBytes()));
    assertThat(obj).isNotNull();
}

Fails with org.geotoolkit.data.geojson.utils.GeoJSONParser parseGeoJSONObject AVERTISSEMENT: Error need type before coordinates java.io.IOException: Parsing error, expect object field name value but got null

So according to the message, GeoJSONParser.java knows about the issue.

also, the returned object, GeoJSONObject is not very convenient, as it is not recognized by the rest of geoTK. One need to cast it to a geometry, GeoJSONGeometry geoJsonGeom = (GeoJSONGeometry) geoJSONObject; to make any use of it. Would it be possible that GeoJSONParser.parse(..) directly return a GeoJSONGeometry ?

thanks !

Geotk stack version : 5.0.0-MC0082

alexismanin commented 3 years ago

Hello,

Thank you for the detailed report.

  1. I confirmed the bug on my side. We will look into this property ordering problem, although I cannot say when. We will update this issue at the time.

  2. The GeoJSONParser is a low-level API, designed for internal work mostly. As it is capable of reading many inputs (FeatureCollection/Feature/Geometry), its output is not typed precisely. You can otherwise read your Geojson dataset using the DataStore API, which will return Feature objects directly. The Feature API aims to represent dynamically typed entities, and is the API used by Geotk rendering engine and processes. Also, Geojson geometries are convreted to JTS geometries.  However, it does not support streaming access, so you have to provide it a file path or URI.

Here is an example of DataStore API usage :

import java.nio.file.Paths;
import java.util.stream.Stream;
import org.geotoolkit.feature.FeatureExt;
import org.geotoolkit.storage.geojson.GeoJSONProvider;
import org.geotoolkit.storage.geojson.GeoJSONStore;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyType;

// Connect to datasource
try (GeoJSONStore store = new GeoJSONStore(new GeoJSONProvider(), Paths.get("/path/to/geojson/file"), 7)) {
 // print attributes available. It's more a guess than a precise report du to dynamic typing of GeoJSON
 final FeatureType dataType = store.getType();
 System.out.println(dataType);

 // Identify main geometric property from data type
 final PropertyType geometryProperty = FeatureExt.getDefaultGeometry(dataType);
 final String geometryName = geometryProperty.getName().toString();

 // Read features / geometries
 try (Stream<Feature> features = store.features(false)) {
 features.map( f -> f.getPropertyValue(geometryName))
 .forEach(System.out::println);
 }
}

Regards,

jmbourdaret commented 3 years ago

Thanks for the detailed information Alexis ! I'm using this to get the BBox (Enveloppe) of a given geojson in an ETL workflow, so I would prefer not to use a File in the process. Eventually, I managed to ensure the order of properties in the geoJson, so it is not an issue anymore for me. Still, I've tried to experiment with your solution, and ran into some things you might want to know: it is most probably because I'm using version 5.0.0-MC0082 (on geomatys repo) GeoJSONStore does not have a method called features, and I could not find an equivalent to get a collection/stream of Features. Maybe because it does not implments FeatureSet of apache SIS 2.0-M0070

Anyway, I'm in no need of a fix on this one.
Thanks for the update !