Skip to Content

GeoJSON, nouveau lingua franca en géomatique ?


Il y quelques années,  Howard Butler, Martin Daly, Allan Doyle, Sean Gillies, Tim Schaub et Christopher Schmidt (quelques grands noms de la planète géomatique OpenSource) se sont mis en tête de créer le format le plus simple possible pour représenter et échanger les données géospatiales (géométries et attributs), avec en vue, les services WEB.

Leur choix s'est tout de suite porté vers le format JSON (de préférence au format XML) et ainsi est né  GeoJSON dont la première mouture a été publiée en 2008 en une page: The GeoJSON Format Specification.

  • le format prend en charge toutes les géométries de l'OGC (tag "geometry"):
    • {"type": "Point", "coordinates": [50.0, 70.0]}
    • {"type": "LineString","coordinates": [[50.0, 70.0], [80.0, 40.0]]}
    • {type": "Polygon","coordinates": [[[50.0, 70.0], [80.0, 40.0], [20.0, 10.0], [30.0, 60.0], [50.0, 70.0]]]}
    • plus les MultiPoints, les MultiLineString, les MultiPolygon, ...,  et les géométries 3D.
  • il prend aussi en charge les attributs qui peuvent être de plusieurs types (tag "properties"):
    • {"prop0": "valeur0"}
    • {"prop1": {"moi": "lui"}}
  • ensuite tout est assemblé suivant le principe d'une collection d'objets (tag "type"= "FeatureCollection" comprenant plusieurs features):
    • { "type": "FeatureCollection",
        "features": [
          { "type": "Feature",
            "geometry": {"type": "Point", "coordinates": [50.0, 70.0]},
            "properties": {"prop0": "valeur0", "prop1": "valeur1", ...,"propn": "valeurn"}
            ]},
          { "type": "Feature",
            "geometry": "type": "Point", "coordinates": [80.0, 40.0],
             ...
          ]}
  • à l'inverse des fichiers shapefiles ou des bases de données géospatiales, plusieurs types de géométries  peuvent coexister dans une FeatureCollection:
    • { "type": "FeatureCollection",
        "features": [
          { "type": "Feature",
            "geometry": {"type": "Point", "coordinates": [50.0, 70.0]},
            "properties": {"prop0": "valeur0"}
            },
          { "type": "Feature",
            "geometry": {"type": LineString","coordinates": [[50.0, 70.0], [80.0, 40.0]]}
            "properties": {"prop0": "valeur3","prop1": "valeur4"}
            },
          { "type": "Feature",
             "geometry": {type": "Polygon","coordinates": [[[50.0, 70.0], [80.0, 40.0], [20.0, 10.0], [30.0, 60.0], [50.0, 70.0]]]},
             "properties": {"prop0": "valeurn","prop1": {"moi": "lui"}
           },
          ....
           ]}

       
  • peuvent aussi y figurer le système de projection, de diverses manières (tag "crs"), et un cadre (Bounding box, tag "bbox")
    • { "type": "FeatureCollection",
      "bbox": [100.0, 0.0, 105.0, 1.0],
      "features": [...]}

Réactions

  • Trop simple, trop lourd, enfantin, pas sérieux, ridicule, faux,...,  ont affirmé certains (voir, entre autres, les réactions sur la liste QGIS-Developer à la proposition de kimaidou Get rid of Shapefiles ! Go GeoJSON ! ), mais générique, facile à lire et à écrire quelque soit le langage de programmation, sérialisable, portable, et autodéfini;
  • Paradoxalement, son succès a été très rapide. En peu de temps, il a été adopté par Google, Bings Map, Yahoo Maps, OpenLayers, Leaflet, CartoDB, D3js, App coverage d'Apple (JavaScript), GitHub, GeoServer (serveur cartographique) ou GeoDjango (serveur cartographique Python), Safe Sofware FME, de multiples librairies Python (voir plus bas) et les bases de données NoSQL comme MongoDB ou CouchDB qui utilisaient déjà le format JSON (voir Le NoSQL dans le domaine géospatial : MongoDB avec JavaScript ou Python, ArcGIS et Quantum Gis et Le NoSQL dans le domaine géospatial : CouchDB et GeoCouch (Couchbase), shp2geocouh, importation de shapefiles et serveur cartographique).
  • De plus, grâce à GDAL/OGR, Quantum GIS, PostGIS ou SpatiaLite peuvent lire ou écrire des couches GeoJSON;
  • Toutes les autres implémentations du format sont reprises dans GeoJSON users (Java, Ruby, php, etc.)

Pourquoi ?

  • Essentiellement du fait de sa simplicité pour la représentation (simple fichier texte) et le transfert de données (format JSON, adapté à Internet), bien qu'il ne soit pas certifié ISO19107 (OGC) comme le souligne ironiquement Sean Gillies dans GeoJSON is Spectacularly Wrong,Yet Somehow Right Enough.

Avec JavaScript:

Quelques exemples simples illustreront son intérêt:

  • Edit GeoJSON de Tom MacWright: dessinez sur la carte et récupérez les données;
  • GeoJSONLint composer ou  coller, validez et visualisez vos couches GeoJSON en «live»;
  • Wikigeo vous permet de chercher les articles de Wikipedia qui fournissent des coordonnées géographiques;
  • uMap qui permet de créer des cartes personnalisées à partir d'OpenSteetMap, soit en les dessinant, soit en les important (GeoJSON) (voir exemple à partir d'une couche géologique introduite dans ce format à GeoJSON import);
  • et maintenant GitHub, placez un fichier texte au format GeoJSON dans un de vos «repository» et il apparait directement sur un fond OpenStreetMap (voir mon exemple à exemple de fichier GeoJSON) ;
  • même plus, vous pouvez  récupérer cette couche dans QGIS (voir: GeoJSON on GitHub: Now What?)

Sans parler des très nombreux exemples sur Internet:

Avec Python (GeoJSON et __geo_interface__):

Si l'on regarde la structure du format JSON, il est facile de constater qu'elle correspond à un dictionnaire Python (dict= {}) qui peut être manipulé en tant que tel. Rien d'étonnant à ce que le format ait été adopté par la plupart des modules géospatiaux:

  • geojson
  • Shapely
  • Fiona
  • descartes
  • pygeoif, version simplifiée de Shapely
  • PySAL
  • ArcPy
  • PyShp, version adaptée par Christian Lederman
  • osgeo.ogr:  osgeo.ogr.Feature.ExportToJson()
  • PyQGIS avec le nouvel API de la version 1.9/2.0:  geom.exportToGeoJSON()

Mais, pour la plupart, cela ne concerne encore que le tag "geometry" et pas les autres. C'est pourquoi Sean Gillies a proposé le __geo_interface__ (GeoJSON-like protocol for geo-spatial (GIS) vector data) qu'il a implémenté dans Fiona (lecture et écriture, voir Python: traitement des couches vectorielles dans une perspective géologique, lecture et enregistrement des couches sous forme de dictionnaires avec le module Fiona) et dans Shapely (implémentés ensuite dans PySAL, pygeoif, PyShp et ogr):

import fiona   
f = fiona.open('point.shp')  
f.next()  
{'geometry': {'type': 'Point', 'coordinates': (161821.09375, 79076.0703125)}, 'id': '0', 'properties': {u'DIP_DIR': 120, u'STRATI_TYP': 1, u'DIP': 30}}
f.next()['geometry']['coordinates']  
(161485.09375, 79272.34375)  
f.next()['properties']['DIP']  
55

qui peut maintenant être parfaitement adapté au module PyShp (voir  PyShp as Fiona (with the GeoJSON-like protocol))::

import shapefile
def records(fichier):  
    # génerateur
    reader = shapefile.Reader(fichier)  
    fields = reader.fields[1:]  
    field_names = [field[0] for field in fields]  
    for sr in reader.shapeRecords():  
        geom = sr.shape.__geo_interface__  
        atr = dict(zip(field_names, sr.record))  
        yield dict(geometry=geom,properties=atr)    
  
a = records('point.shp')
a.next()
{'geometry': {'type': 'Point', 'coordinates': (161821.09375, 79076.0703125)}, 'properties': {'DIP_DIR': 120, 'STRATI_TYP': 1, 'DIP': 30}}
a.next()['geometry']['coordinates']
(161485.09375, 79272.34375)
a.next()['properties']['DIP']
55

et au nouvel API de PyQGIS:

layer = qgis.utils.iface.activeLayer()  
def records(layer):  
    fields = layer.pendingFields()   
    field_names = [field.name() for field in fields]   
    for elem in layer.getFeatures():  
          geom= elem.geometry()  
          atr = dict(zip(field_names, elem.attributes()))  
          yield dict(geometry=geom.exportToGeoJSON(),properties=atr)  
c = records(layer) 
c.next() 
{'geometry': u'{ "type": "LineString", "coordinates": [ [164917.66073716, 115230.16694565], [170806.15565476, 116401.17445767] ] }', 'properties': {u'id': 1,u'test':u'ligne'}}

et ogr avec .ExportToJson()...

Une simple boucle pour obtenir la représentation GeoJSON complète d'une couche, un copier-coller dans les exemples en JavaScript présentés et l'affaire est réglée...

Problèmes et solutions présentées (TopoJSON)

Indépendamment des réactions déjà soulignées, très vives par moments, le principal problème est, vous vous en doutez, la taille des fichiers textes résultants. Diverses solutions ont été proposées, (comme How to minify GeoJSON files?), mais la plus convaincante est le format TopoJSON de Mike Bostock, extension de GeoJSON qui se base sur les relations topologiques de ESRI ArcInfo  (un seul arc pour la limite commune entre 2 polygones, par exemple). Le gain de taille est significatif (environ 80%) mais le format est récent et donc encore relativement peu utilisé.  Tout ce que l'on peut dire est que la boucle est bouclée, de ArcInfo aux shapefiles et.... retour.

Conclusions

"A remarkably simple feature, which i think significantly disrupts the traditional geospatial market" est un avis parmi d'autres sur le format GeoJSON (feomike.github.io/post/thoughts-on-disruption.htm). D'autres sont beaucoup plus négatifs, notamment les « professionnels » des SIGs et des SGBD pour qui c'est trop « simple ». C'est vrai, pas besoin de serveur cartographique, de REST ou de SOAP, de ..., un simple fichier texte et du JavaScript suffisent.

C'est en effet bien Internet et la cartographie en ligne qui ont assuré le succès inespéré du format et les utilitaires de conversion abondent, payants ou non: de KML vers GeoJSON (et vice-versa) et  de (ce que vous voulez) vers GeoJSON alors qu'avec ogr2ogr:

ogr2ogr -f "GeoJSON" -lco votre.geojson votre.shp

Son adoption récente par ESRI dans ArcPy (à ne pas confondre avec l' ESRI Json de l'API REST) lui apportera sans doute une certaine reconnaissance « officielle »:

import arcpy 
geojson_point = {"type": "Point", "coordinates": [50.0, 75.0]} 
point = arcpy.AsShape(geojson_point) 

petit emprunt à Shapely...

from shapely.geometry import shape
geojson_point = {"type": "Point", "coordinates": [50.0, 75.0]}
point = shape(geojson_point) 
print point
POINT (50.00 75.00)

Mais il faut garder en mémoire son objectif: pas de styles ou d'autres fioritures ici, ce n'est qu'un format d'échange qui se veut universel, comme l'est le format WKT, mais bien plus complet et plus souple à utiliser.

GeoJSON is not Lat, Lng
    To match OGR
    To match KML
    It surprises the naive
    It annoys the expert
    It is what it is
The Web loves JSON because it is
    minimal, portable, textual
    self-describing
    a subset of JavaScript
    (and other languages with Map literals)
The Little Format that Could
    GeoJSON gets many things right
    It gets some things wrong
    Requirements, opinions, and tastes differ
    GeoJSON is flexible and evolvable
    It's been a valuable experiment in standards making

GeoJSON is Spectacularly Wrong,Yet Somehow Right Enough.

Les gens de chez Safe Software (FME) ne se sont pas trompés en résumant la situation dans Spatial Data Formats: ‘Esperanto’ vs ‘Lingua Franca’ et en adoptant dès le début le format (d'où le titre de l'article).


Site officiel : Le NoSQL dans le domaine géospatial : MongoDB avec JavaScript ou Python, ArcGIS et Quantum Gis
Site officiel : Le NoSQL dans le domaine géospatial : CouchDB et GeoCouch (Couchbase), shp2geocouh, importation de shapefiles et serveur cartographique
Site officiel : Python: traitement des couches vectorielles dans une perspective géologique, lecture et enregistrement des couches sous forme de dictionnaires avec le module Fiona


Creative Commons License
licence Creative Commons Paternité-Pas d'Utilisation Commerciale-Partage des Conditions Initiales à l'Identique Commerciale 2.0 France

Commentaires

Et maintenant ?

5 ans et demi après cet article, alors que QGIS 3 et son utilisation par défaut du format GeoPackage gpkg vont sans doute propulser en avant le gpkg, soutenu en outre par l'OGC, mais passablement "boite noire" à mon humble avis, j'aimerais beaucoup avoir l'actualisation des informations et opinions de Martin Laloux (et Marc Léobet aussi !) exprimées ci-dessus.

Comme programmeur, je trouve commode d'accéder directement à un bas niveau de représentation de la donnée, et donc j'ai toujours tendance à préférer un format texte.

Ayant débuté dans les SIG par la lecture de 'Understanding GIS with PC Arc/Info', et ayant de ce fait le modèle topologique gravé dans la tête, j'aimerais aussi un développement plus long sur TopoJSON, car vos articles sont toujours particulièrement éclairants.

Le problème c'est que c'est

Le problème c'est que c'est un combat d'arrière garde (SOAP XML vs  REST JSON JavaScript):

"Yes, twelve years after the birth of JSON, five years after the release of the ESRI REST API and its embedded JSON syntax, and five years after the release of GeoJSON 1.0, OGC is still has no entry in the JSON space. Between Esri and GeoJSON, the utility of JSON in web mapping applications has been roundly proven. In the ESRI arena, find me anyone who willingly uses the SOAP API these days while the adoption of support for GeoJSON across the open-source GIS world speaks volumes. The industry has voted with its feet and its code as to what it prefers.

There’s probably a lively discussion to be had about where JSON should fit into OGC’s priorities. What is clear, however, is that Javascript and JSON are driving the web at large and the web-mapping space in the geospatial market. With no official stance of any kind in this area, it becomes increasingly difficult to take OGC seriously in matters of the modern web".

de OGC Abandons the Web

GeoJSON & INSPIRE

En direct de la Conference INSPIRE 2013 : l'article tombe à point nommé dans un environnement mouvant, où le lien entre INSPIRE (l'IG pure et dure) et Open Data (la donnée à la pelle mais souvent en vrac) est omniprésent. Au moment où le Royaume-Uni et la Commission européenne pose la question du recours au W3C pour produire des widgets et des apps. La question du recours à GeoJSON a même été posée dans le groupe chargé spécifiquement des services en réseau sur le thème : "qu'en fait-on". Pas de réponse à ce jour, mais à titre personnel, je pense que l'on va vers des widgets et des apps alimentés, par en-dessous, par des services OGC.

Cordialement

Poster un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.