From ff9a19c5dd8765a89ddd9537a07f6a020d5a86c6 Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Tue, 30 Jun 2015 18:09:28 +0000 Subject: [PATCH] #2683, improve geojson srs handling (input) git-svn-id: http://svn.osgeo.org/postgis/trunk@13767 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/lwin_geojson.c | 61 +++++++++++++++++++++++-------------- postgis/lwgeom_export.c | 15 ++++++--- postgis/lwgeom_in_geojson.c | 30 ++++++++++-------- regress/in_geojson.sql | 4 +++ regress/in_geojson_expected | 4 +++ 5 files changed, 73 insertions(+), 41 deletions(-) diff --git a/liblwgeom/lwin_geojson.c b/liblwgeom/lwin_geojson.c index ce2e15180..9e6169473 100644 --- a/liblwgeom/lwin_geojson.c +++ b/liblwgeom/lwin_geojson.c @@ -152,10 +152,11 @@ parse_geojson_point(json_object *geojson, int *hasz, int root_srid) LWDEBUGF(3, "parse_geojson_point called with root_srid = %d.", root_srid ); coords = findMemberByName( geojson, "coordinates" ); - if ( ! coords ) { + if ( ! coords ) + { geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4); - return NULL; - } + return NULL; + } pa = ptarray_construct_empty(1, 0, 1); parse_geojson_coord(coords, hasz, pa); @@ -176,10 +177,11 @@ parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid) LWDEBUG(2, "parse_geojson_linestring called."); points = findMemberByName( geojson, "coordinates" ); - if ( ! points ) { + if ( ! points ) + { geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4); - return NULL; - } + return NULL; + } pa = ptarray_construct_empty(1, 0, 1); @@ -322,10 +324,11 @@ parse_geojson_multilinestring(json_object *geojson, int *hasz, int root_srid) } poObjLines = findMemberByName( geojson, "coordinates" ); - if ( ! poObjLines ) { + if ( ! poObjLines ) + { geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4); - return NULL; - } + return NULL; + } if( json_type_array == json_object_get_type( poObjLines ) ) { @@ -436,10 +439,11 @@ parse_geojson_geometrycollection(json_object *geojson, int *hasz, int root_srid } poObjGeoms = findMemberByName( geojson, "geometries" ); - if ( ! poObjGeoms ) { + if ( ! poObjGeoms ) + { geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4); - return NULL; - } + return NULL; + } if( json_type_array == json_object_get_type( poObjGeoms ) ) { @@ -462,16 +466,18 @@ parse_geojson(json_object *geojson, int *hasz, int root_srid) json_object* type = NULL; const char* name; - if( NULL == geojson ) { + if( NULL == geojson ) + { geojson_lwerror("invalid GeoJSON representation", 2); - return NULL; - } + return NULL; + } type = findMemberByName( geojson, "type" ); - if( NULL == type ) { + if( NULL == type ) + { geojson_lwerror("unknown GeoJSON type", 3); - return NULL; - } + return NULL; + } name = json_object_get_string( type ); @@ -541,15 +547,24 @@ lwgeom_from_geojson(const char *geojson, char **srs) if (poObjSrsType != NULL) { json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" ); - json_object* poNameURL = findMemberByName( poObjSrsProps, "name" ); - const char* pszName = json_object_get_string( poNameURL ); - *srs = lwalloc(strlen(pszName) + 1); - strcpy(*srs, pszName); + if ( poObjSrsProps ) + { + json_object* poNameURL = findMemberByName( poObjSrsProps, "name" ); + if ( poNameURL ) + { + const char* pszName = json_object_get_string( poNameURL ); + if ( pszName ) + { + *srs = lwalloc(strlen(pszName) + 1); + strcpy(*srs, pszName); + } + } + } } } lwgeom = parse_geojson(poObj, &hasz, 0); - json_object_put(poObj); + json_object_put(poObj); lwgeom_add_bbox(lwgeom); diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c index b16d08185..56d1d5b00 100644 --- a/postgis/lwgeom_export.c +++ b/postgis/lwgeom_export.c @@ -112,8 +112,11 @@ int getSRIDbySRS(const char* srs) SPI_finish(); return 0; } - sprintf(query, "SELECT srid \ - FROM spatial_ref_sys WHERE auth_name||':'||auth_srid = '%s'", srs); + sprintf(query, + "SELECT srid " + "FROM spatial_ref_sys, " + "regexp_matches('%s', E'([a-z]+):([0-9]+)', 'gi') AS re " + "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid", srs); err = SPI_exec(query, 1); if ( err < 0 ) @@ -126,9 +129,11 @@ int getSRIDbySRS(const char* srs) /* no entry in spatial_ref_sys */ if (SPI_processed <= 0) { - sprintf(query, "SELECT srid \ - FROM spatial_ref_sys WHERE \ - 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid = '%s'", srs); + sprintf(query, + "SELECT srid " + "FROM spatial_ref_sys, " + "regexp_matches('%s', E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re " + "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid", srs); err = SPI_exec(query, 1); if ( err < 0 ) diff --git a/postgis/lwgeom_in_geojson.c b/postgis/lwgeom_in_geojson.c index e69d99b03..f95c63877 100644 --- a/postgis/lwgeom_in_geojson.c +++ b/postgis/lwgeom_in_geojson.c @@ -35,7 +35,7 @@ Datum postgis_libjson_version(PG_FUNCTION_ARGS) PG_RETURN_NULL(); #else /* HAVE_LIBJSON */ # ifdef JSON_C_VERSION - const char *ver = json_c_version(); + const char *ver = json_c_version(); # else const char *ver = "UNKNOWN"; # endif @@ -56,24 +56,28 @@ Datum geom_from_geojson(PG_FUNCTION_ARGS) LWGEOM *lwgeom; text *geojson_input; char *geojson; - char *srs = NULL; + char *srs = NULL; /* Get the geojson stream */ - if (PG_ARGISNULL(0)) PG_RETURN_NULL(); + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); + geojson_input = PG_GETARG_TEXT_P(0); geojson = text2cstring(geojson_input); - lwgeom = lwgeom_from_geojson(geojson, &srs); - if ( ! lwgeom ) { - /* Shouldn't get here */ - elog(ERROR, "lwgeom_from_geojson returned NULL"); - PG_RETURN_NULL(); - } + lwgeom = lwgeom_from_geojson(geojson, &srs); + if ( ! lwgeom ) + { + /* Shouldn't get here */ + elog(ERROR, "lwgeom_from_geojson returned NULL"); + PG_RETURN_NULL(); + } - if ( srs ) { - lwgeom_set_srid(lwgeom, getSRIDbySRS(srs)); - lwfree(srs); - } + if ( srs ) + { + lwgeom_set_srid(lwgeom, getSRIDbySRS(srs)); + lwfree(srs); + } geom = geometry_serialize(lwgeom); lwgeom_free(lwgeom); diff --git a/regress/in_geojson.sql b/regress/in_geojson.sql index b41ac6fc9..45330a7a9 100644 --- a/regress/in_geojson.sql +++ b/regress/in_geojson.sql @@ -41,3 +41,7 @@ SELECT 'geomfromgeojson_z_02', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"LineString SELECT 'geomfromgeojson_zm_01', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"Point","coordinates":[1,2,3,4]}')); SELECT 'geomfromgeojson_zm_02', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"LineString","coordinates":[[1,2,3,4],[2,3,4,5]]}')); +SELECT 'geomfromgeojson_srs_1', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:EPSG::4326"}}}')); +SELECT 'geomfromgeojson_srs_2', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}')); +SELECT 'geomfromgeojson_srs_3', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","props":{"name":"urn:ogc:def:crs:EPSG::4326"}}}')); +SELECT 'geomfromgeojson_srs_4', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","properties":{"nm":"EPSG:4326"}}}')); diff --git a/regress/in_geojson_expected b/regress/in_geojson_expected index 5e10f1084..ddedb906d 100644 --- a/regress/in_geojson_expected +++ b/regress/in_geojson_expected @@ -23,3 +23,7 @@ geomfromgeojson_z_01|POINT(1 2 3) geomfromgeojson_z_02|LINESTRING(1 2 3,2 3 4) geomfromgeojson_zm_01|POINT(1 2 3) geomfromgeojson_zm_02|LINESTRING(1 2 3,2 3 4) +geomfromgeojson_srs_1|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1)) +geomfromgeojson_srs_2|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1)) +geomfromgeojson_srs_3|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1)) +geomfromgeojson_srs_4|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1)) -- 2.50.1