I have a GeoDataFrame with some of its attributes that are geometries (only the position
is the one which was interpreted as the active geometry when loading the data from PostGIS):
import psycopg2
import geopandas as gpd
import json
# define a conn object for database retrieval
sql = 'SELECT id, position, buffer1, buffer2, buffer3 FROM table WHERE id = 11;'
gdf = gpd.read_postgis(sql, conn, geom_col='position')
Which leads to this resulting gdf
:
I dump it as follow before returning this object (it's a function return value):
return json.loads(gdf.to_json())
It looks like this:
{
"type": "FeatureCollection",
"features": [
{
"id": "0",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [8.54, 47.36, 490.6]
},
"properties": {
"id": 1,
"buffer1": {
"type": "Polygon",
"coordinates": [
[ [8.5, 47.3],
(...)
[ 8.4, 47.4]
]
]
},
"buffer2": {
"type": "MultiPolygon",
"coordinates": [
[ [
[8.5, 47.4],
(...)
[ 8.5, 47.6]
] ]
]
},
"buffer3": {
"type": "MultiPolygon",
"coordinates": [
[ [
[8.2, 47.2],
(...)
[8.3, 47.7]
] ]
]
}
}
}
]
}
Several points drew my attention from here:
First; the CRS is not dumped. I don't know why?! It is definitely in the GeoDataFrame because when I ask for
gdf.CRS
it prints all the details of apyproj.crs.crs.CRS
object.Second point; all the other geometries are stored in the
'properties'
entry. It apparently "decided" to build aFeatureCollection
(out of one record from the database, which is strange, but I'll live with it...). I would have preferred to have these extra 'bufferX' geometries as actualFeatures
inside thatFeatureCollection
instead of just asproperties
. In such a structure for example; https://openlayers.org/en/latest/examples/geojson.html?q=geojson. So it's a mess to bring them back to standard single GeoJSON object (it's possible but not clean).Last point; the
FeatureCollection
got the id0
, and my id (11
) is also stored in theproperties
. My wanted output would be like this:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [8.54, 47.36, 490.6]
},
"properties": {
"id": 11,
"name": "position"
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[ [8.5, 47.3],
[ 8.4, 47.4]
]
]
},
"properties": {
"id": 11,
"name": "buffer1"
}
},
{
"type": "Feature",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[ [
[8.5, 47.4],
[ 8.5, 47.6]
] ]
]
},
"properties": {
"id": 11,
"name": "buffer2"
}
},
{
"type": "Feature",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[ [
[8.2, 47.2],
[8.3, 47.7]
] ]
]
},
"properties": {
"id": 11,
"name": "buffer3"
}
}
]
}
My question is: from an initial GeoDataFrame which has several geometry columns, is there a simple way to construct a valid GeoJSON object which has a single FeatureCollection
containing each of these geometries as child Features
(with a name
attribute corresponding to its original column name and an id
corresponding to the id used to get the data from the PostGIS database) and not as currently properties
of a FeatureCollection
containing only the active geometry column as a Feature
and all other geometries as simple 'properties'?
There isn't much options yet to the .to_json()
method. :(
Useful link: https://jsonformatter.org/