2

When testing the following code:

from osgeo import gdal
import json


def read_file(filename):
    f = gdal.VSIFOpenL(filename, "rb")
    if f is None:
        return None
    content = gdal.VSIFReadL(1, 10000, f).decode('UTF-8')
    gdal.VSIFCloseL(f)
    return content


gdal.VectorTranslate('out.json', """{
  "type": "FeatureCollection",
  "features": [
      { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": "coordinates":[[[-188.56933593749997,61.58549218152362],[-173.9794921875,61.58549218152362],[-173.9794921875,66.00015035652659],[-188.56933593749997,66.00015035652659],[-188.56933593749997,61.58549218152362]]] } },
  ]
}""", format = 'GeoJSON', layerCreationOptions = ['RFC7946=YES', 'WRITE_BBOX=YES'])

got = read_file('/vsimem/out.json')
gdal.Unlink('/vsimem/out.json')

print json.loads(got)

from this answer, the file out.json is empty. The folder is with all permissions for writing allowed. When testing the method gdal.OpenEx, is possible to load an object, but still the method gdal.VectorTranslate returns an empty geojson when trying to pass this new loaded object as a srcDS object. Any hint on solving this issue?

5
  1. Your JSON is invalid - you have entered the "coordinates" key twice.

  2. You are trying to read from a different file than you are writing to. You are trying to write to out.json which will be a file on disk in the current working directory. You need to write to '/vsimem/out.json'

To pick up these issues more easily, use gdal.UseExceptions() so GDAL raises an exception instead of returning None when it can't open something.

I've also updated your read_file script to find the length automatically.

from osgeo import gdal
import json

def read_file(filename):
    vsifile = gdal.VSIFOpenL(filename,'r')
    gdal.VSIFSeekL(vsifile, 0, 2)
    vsileng = gdal.VSIFTellL(vsifile)
    gdal.VSIFSeekL(vsifile, 0, 0)
    return gdal.VSIFReadL(1, vsileng, vsifile)

gdal.UseExceptions() #Fail when can't open!

gjs = '''{
  "type": "FeatureCollection",
  "features": [
      { "type": "Feature", "geometry": { "type": "Polygon", "coordinates":[[[-188.56933593749997,61.58549218152362],[-173.9794921875,61.58549218152362],[-173.9794921875,66.00015035652659],[-188.56933593749997,66.00015035652659],[-188.56933593749997,61.58549218152362]]] } },
  ]
}'''

ds = gdal.VectorTranslate('/vsimem/out.json', gjs, format = 'GeoJSON', layerCreationOptions = ['RFC7946=YES', 'WRITE_BBOX=YES'])

print(ds)

got = read_file('/vsimem/out.json')

#Works
print(got)

#Fails as the json module can't read you json (nor can https://jsonlint.com)
print(json.loads(got))

And once you have valid GeoJSON, gdal.VectorTranslate will still return an empty dataset. This is a known python GDAL "gotcha". The data doesn't get written until the dataset is closed and dereferenced.

This works:

from osgeo import gdal
gdal.UseExceptions()
srcDS = gdal.OpenEx('input.geojson')
ds = gdal.VectorTranslate('output.geojson', srcDS=srcDS, format = 'GeoJSON', layerCreationOptions = ['RFC7946=YES', 'WRITE_BBOX=YES'])

#Dereference and close dataset, then reopen.
del ds
ds = gdal.OpenEx('output.geojson')

print(srcDS.GetLayer(0).GetFeatureCount())
print(ds.GetLayer(0).GetFeatureCount())
  • Luke, if I want to use this example in Python 2.x, is there a significant change in the method signature? – Ricardo Barros Lourenço Sep 13 '17 at 12:14
  • @Ricardo no, the code will run as is in python 2.7. However, the gdal.VectorTranslate is only available in GDAL 2x,not GDAL 1.x – user2856 Sep 13 '17 at 12:21
  • Ok @Luke . I'm already using GDAL 2.1.x on Python 2.x, but when I use the code you've written, it dumps an empty JSON. Perhaps is an issue on my package install (I'm using GDAL on a MacOS). – Ricardo Barros Lourenço Sep 13 '17 at 12:30
  • @Ricardo the RFC7946=YES creation option is only supported at GDAL >= 2.2 as stated in the GeoJSON driver documentation – user2856 Sep 14 '17 at 2:35
  • This is not really a Python gotcha in that case. If you did the same thing to a shapefile or GeoPackage, which are fully capable read-write-update drivers, that would work. The GeoJSON driver is a "hybrid" one. On writing, it is a pure streaming writing driver (it doesn't keep the object in memories and write them on-the-fly). Currently it doesn't maintain the feature count (it could). When reading an existing GeoJSON file, it ingests it fully in memory. So the driver could potentially be improved to do that when reading operations are done, but that remains a marginal need, hence not done yet – Even Rouault Sep 22 '17 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.