[GIS] ogr2ogr from Postgres to GeoJSON missing crs key

geojsonogr2ogr

I'm using ogr2ogr to convert some OSM data for Greenland (not really important for the question), from a PostGIS database to a file containing GeoJSON.

The problem is that the GeoJSON gets written without the crs attribute, even though I'm reprojecting to a non-4326 coordinate system (3189 to be specific). See below how I do this.

The srid of data in geometry column in the database table is 4326. I use the t_srs "epsg:3189" option to transform the coordinates, and this seems to work, i.e. the coordinates are not Lat/Lon.

Command used:

ogr2ogr -f "GeoJSON" greenland_coast.geojson \
  PG:"host=localhost user=xxx dbname=greenland_osm password=xxx" \
  -sql "select linestring from ways" -t_srs "epsg:3189"

Snippet of GeoJSON result:

Notice the missing crs attribute that should indicate that the coordinates are in EPSG:3189.

{
"type": "FeatureCollection",                                                                         
"features": [
  { "type": "Feature", 
    "properties": { }, 
    "geometry": { 
      "type": "LineString", 
       "coordinates": [ 
         [ -548886.066167875193059, 9361706.390365654602647 ], ...]
     }
  },
  ...
]}

The coordinates seem to have been transformed correctly, but there is no crs field telling a reader of the GeoJSON file that the coordinates are in epsg:3189

The GeoJSON spec states:

If no crs member can be so acquired, the default CRS shall apply to
the GeoJSON object … The default CRS is a geographic coordinate
reference system, using the WGS84 datum, and with longitude and
latitude units of decimal degrees.

I assumed that since I'm reprojecting to a non-geographic coordinate system, a crs key-value pair would be written to the GeoJSON (indicating EPSG:3189 in my case).

My question

Which of the following statements is more true?

  • I'm using ogr2ogr wrong
  • My expectations of ogr2ogr are too high
  • There an error in the GeoJSON driver

Best Answer

I had a look at the OGR source, and I think option 2 applies.

#ifdef notdef
    if (poSRS)
    {
        const char* pszAuthority = poSRS->GetAuthorityName(NULL);
        const char* pszAuthorityCode = poSRS->GetAuthorityCode(NULL);
        if (pszAuthority != NULL && pszAuthorityCode != NULL && strcmp(pszAuthority, "EPSG") == 0)
        {
            json_object* poObjCRS = json_object_new_object();
            json_object_object_add(poObjCRS, "type", json_object_new_string("name"));
            json_object* poObjProperties = json_object_new_object();
            json_object_object_add(poObjCRS, "properties", poObjProperties);

            if (strcmp(pszAuthorityCode, "4326") == 0)
            {
                json_object_object_add(poObjProperties, "name", json_object_new_string("urn:ogc:def:crs:OGC:1.3:CRS84"));
            }
            else
            {
                /* FIXME?: the issue is that for geographic SRS, OGR will expose a latitude/longitude axis order */
                /* which is probably not what is written in the file! */
                json_object_object_add(poObjProperties, "name", json_object_new_string(CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszAuthorityCode)));
            }

            const char* pszCRS = json_object_to_json_string( poObjCRS );
            VSIFPrintfL( fpOut_, "\"crs\": %s,\n", pszCRS );

            json_object_put(poObjCRS);
        }
    }
#endif

That #ifdef notdef was added by this commit but I couldn't say why.

Perhaps you can try rebuilding gdal without the #ifdef and #endif?

Related Question