2

I'm attempting to use fiona to write out a number of GeoJSON objects to different layers in a single GeoPackage.

Here's an example json.dumps() representation of the GeoJSON object containing one feature:

{"type": "FeatureCollection",
 "features": [
    {"type": "Feature",
     "geometry": {
         "type": "Polygon",
         "coordinates": [[bunch of coord pairs]]},
     "properties": {
         "dataType": "Shapefile",
         "fname": "cb_2018_us_state_500k.shp",
         "path": "file:///C:\\Data\\Foundation\\US\\cb_2018_us_state_500k",
         "native_crs": 4269,
         "lastmod": "2019-04-15T15:55:28"}
}]}

This feature collection, call it feature_collection_a, is stashed as one of many, sharing the same schema, in a dict I'm iterating over to write the outputs:

layers = {'level_00': feature_collection_a,
          'level_01': feature_collection_b}

So I try to do (assuming I've imported from_epsg from fiona.crs):

path = 'C:/path/to/someoutput.gpkg'
driver = 'GPKG'
schema = {'geometry': 'Polygon',
          'properties': OrderedDict([
              ('dataType', 'str'),
              ('fname', 'str'),
              ('path', 'str'),
              ('native_crs', 'int'),
              ('lastmod', 'str')])}

for k, v in layers.items():
    if v:
        with fiona.open(path, 'w',
                        schema=schema,
                        driver=driver,
                        crs=from_epsg(4326),
                        layer=k) as outlayer:
            outlayer.write(v)

This gives me:

Record does not match collection schema: dict_keys([]) != ['path', 'fname', 'dataType', 'native_crs', 'lastmod']

Since I am using an OrderedDict() to construct both the properties element (in the raw geojson object represented by v) and in schema, I am confused as to why this is failing.

When I try it with geopandas it works fine:

import geopandas as gpd

for k, v in layers.items():
    if v:
        gdf = gpd.GeoDataFrame.from_features(v)
        gdf.crs = 'EPSG:4326'
        gdf.to_file(path, driver=driver, layer=k)

And since geopandas uses fiona for its r/w ops, it tells me the problem is not with fiona but with how I'm (mis)using it.

I could just use geopandas to do this, but (A) I feel like that's lazy and (B) relying on a very high level package like GeoPandas makes my script more fragile than I'd like.

1
  • @nmtoken what makes you think that this applies here? Commented Dec 8, 2020 at 18:16

1 Answer 1

2

You can use the writerecords method (it takes a list of Features) instead of the write methods (which takes a FeatureCollection) and it appears to works :

for k, v in layers.items():
    if v:
        with fiona.open(path, 'w',
                        schema=schema,
                        driver=driver,
                        crs=from_epsg(4326),
                        layer=k) as outlayer:
            outlayer.writerecords(v['features']) # <- changed this line

Using the writerecords methods also seems to be what is done internally by geopandas (here in file.py)

However I don't know why it doesn't work as expected with write.

1
  • Interesting, that works. I'll mark this as correct but I'm also a bit confused... maybe I'll create an issue at the repo on this.
    – auslander
    Commented Dec 10, 2020 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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