Modificare la struttura di un file JSON e creare un GeoJSON

Il caso delle API dei dati EFFIS

Andrea Borruso
Jul 26, 2017 · 3 min read

Da poco su TANTO abbiamo pubblicato un post sulle API per accedere ai dati dello European Forest Fire Information System (EFFIS).

L’output di queste API è in JSON, formato di grande comodità per sviluppare siti web, applicazioni, bot, ecc., basati su questi dati. Tra i dati esposti anche dei dati geografici (come i poligoni che delimitano le aree bruciate) e nasce spontanea la voglia di averli in un formato file nativamente spaziale, con il quale sarà immediata la visualizzazione, l’editing e l’analisi anche in un’applicazione GIS.

Visto il formato di output originario e vista la struttura interna di questi dati è naturale pensare di convertirlo in GeoJSON.

A seguire verrà mostrato come eseguire questa conversione a partire da uno degli endpoint disponibili delle API di EFFIS, ovvero quello delle areee bruciate: /rest/2/burntareas/current/.

Da JSON a GeoJSON con jq

jq è una straordinaria utility — open-source e disponibile per qualsiasi sistema operativo — per manipolare sorgenti JSON.

Un esempio “tipo” di output delle API di EFFIS per l’endpoint /rest/2/burntareas/current/è quello di sotto.

I dati “importanti” sono dentro .results[]:

  • .bbox, il bounding box dell'area bruciata;
{
"count": 360,
"next": "http://effis.jrc.ec.europa.eu/rest/2/burntareas/current/?country=IT&format=json&limit=1&offset=1&ordering=-firedate",
"previous": null,
"results": [
{
"objectid": 319401,
"centroid": {
"type": "Point",
"coordinates": [
15.91900524881104,
39.59244913204589
]
},
"bbox": [
15.911960259,
39.588792363,
15.927565351,
39.595131864
],
"id": 168877,
"countryful": "Italy",
"province": "Cosenza",
"commune": "Bonifati",
"firedate": "2017-07-23",
"area_ha": 60,
"broadlea": "98.31000000",
"conifer": "0.00000000",
"mixed": "0.00000000",
"scleroph": "0.00000000",
"transit": "0.00000000",
"othernatlc": "0.00000000",
"agriareas": "1.69000000",
"artifsurf": "0.00000000",
"otherlc": "0.00000000",
"percna2k": "0.00000000",
"lastupdate": "2017-07-23",
"ba_class": "07DAYS",
"mic": "",
"se_anno_cad_data": "",
"shape": {
"type": "Polygon",
"coordinates": [[[15.914439261,39.595029202],[15.914311703,39.59499103],[15.914181904,39.594946449],[15.914050446,39.594895658],[15.913917991,39.594838911],[15.913785154,39.594776469],[15.913652798,39.594708729],[15.914439261,39.595029202]]]
},
"critech": "",
"country": "IT"
}
]
}

La struttura di base di un file GeoJSON, per un layer poligonale, è invece quella di sotto.

I dati “importanti” sono dentro .features[]:

  • .geometry, le coordinate del poligono;
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"tipo": "A"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[13.1396484375,38.238180119798635],[12.83203125,37.82280243352756],[13.623046875,37.84015683604136],[13.1396484375,38.238180119798635]
]
]
}
}
]
}

La struttura della parte geometrica dell’output di EFFIS (contenuta in results[].shape) è in partenza conforme a quella delle specifiche GeoJSON. Quindi basta copiare i dati e rinominare il contenitore da .shape a .geometry.

Mentre nel file JSON di EFFIS non c’è il contenitore .properties, che sarà quindi da creare, per poi inserirgli all'interno i vari campi informativi contenuti nei dati di input.

Il download e la conversione possono essere eseguiti da riga di comando in questa modalità:

curl "URL endpoint EFFIS" | jq 'filtro da applicare all'input' > nomeFileOutput.geojson

Per convertire in GeoJSON le ultime 25 “aree bruciate” in Italia, il comando sarà:

curl "http://effis.jrc.ec.europa.eu/rest/2/burntareas/current/?limit=25&country=IT&ordering=-firedate&format=json" | jq '[.results[] | del(.centroid) | del(.bbox) | .geometry=.shape | del(.shape )] | {"type": "FeatureCollection", features:(map ( {"type": "Feature"}+{"properties": .}+{geometry:.geometry}))} | del(.features[].properties.geometry)' > output.geojson

Il filtro jq (che si può guardare live qui su jqplay) fa per grandi linee questo:

  • entra nei risultati con .results[];

Quanto filtrato viene infine salvato in output nel file output.geojson; ne ho cristallizzato una copia qui (sotto in anteprima).

È un piccolo esempio delle feature di jq, che fra l’altro ha vita più facile in casi come questo, in cui l’input è in partenza ben strutturato.

mappa dinamica con, in celeste. alcuni poligoni GeoJSON di esempio

Per scrivere questo testo mi sono tornati utili tre strumenti che uso spesso: il già citato jqplay (con cui si possono testare i filtri di jq), geojson.io (con cui si ha contezza della struttura di un file GeoJSON) e Gist di GitHub.

tantotanto

Le cose che ci piacciono …

Andrea Borruso

Written by

#data #maps #GIS #baci #condivisione. Orgoglioso di essere presidente di @ondatait

tantotanto

Le cose che ci piacciono …

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade