PostGIS : Import et création de fichiers GeoJSON à la volée

GeoJSON est un format de donnée spatiale open source basé sur le JavaScript Object Notation (JSON). Le format de fichier est structuré par :

  • le type d’objet(s) géographique(s) : Feature ou FeatureCollection pour plusieurs objets;
  • la géométrie liée à l’objet Feature (points, lignes, polygones, multipoints, multilignes, multipolygones) avec les coordonnées;
  • les propriétés liées à l’objet Feature;
  • le système de coordonnées géographiques;

Le GeoJSON est un format standardisé par l’Internet Engineering Task Force (IETF) qui a publié le référentiel RFC7946.

Un fichier GeoJSON est supporté par de nombreux logiciels SIG (QGIS, etc) et les API de webmapping (OpenLayers, etc). Il est aussi possible de l’importer dans une base de données. Dans cet article, on vous présente comment importer et exporter des fichiers GeoJSON depuis la base PostgreSQL / PostGIS (PostgreSQL 9.6).

1. Import d’un fichier GeoJSON dans PostGIS

1.1. Outils SIG utilisés

Il existe plusieurs manières d’importer un fichier GeoJSON dans PostGIS. Ici, on utilise l’outil ogr2ogr de GDAL qui permet de convertir des données d’un format de fichier à l’autre. GDAL est une librairie libre sous licence de l’Open Source Geospatial Foundation (OSGEO) largement utilisée et implémentée dans les logiciels SIG. Il est possible de télécharger les sources ou un exécutable de GDAL sur leur site. Pour une utilisation plus large des outils SIG, le projet OsGeo4W met à disposition des packages de logiciels SIG open sources contenant GRASS, QGIS, Python, MapServer… téléchargeables ici ou sur le site de QGIS. Pour ce tutoriel, on utilisera l’OsGeo4W.

1.2. Structure du fichier GeoJSON utilisé et import de la donnée

La structure non exhaustive du format GeoJSON ci-après est issue du fichier ‘pays.geojson’ (source : OpenLayers) représentant les pays du monde déjà utilisé dans cette démonstration de webmapping. Pour tester les différentes démonstrations de cet article, la donnée est disponible ici.

{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
	{ "type": "Feature", 
			  "properties":  { "id": "AFG", "name": "Afghanistan" }, 
			  "geometry": { "type": "Polygon", "coordinates": [ [ [ 61.210817, 35.650072 ],...] ] } 
	},
	{ "type": "Feature", 
				"properties": { "id": "AGO", "name": "Angola" }, 
				"geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 16.326528, -5.87747 ],...] ] ] } 
	},
	...
]
}

Le fichier est un ensemble d’objets géographiques FeatureCollection, défini par son système de projection crs et les objets géographiques feature, eux-mêmes définis par une géométrie et des propriétés (ici, le code ISO du pays id et le nom du pays en anglais name).

Importons le fichier GeoJSON dans la base de données PostgreSQL en ligne de commande avec ogr2ogr, on lance OsGeo4W. La commande ogr2ogr est basiquement définie comme suit  :

ogr2ogr -f "nom_du_format" destination_du_fichier source_du_fichier

Les formats de fichiers disponibles sont :

-f "ESRI Shapefile"
-f "TIGER"
-f "MapInfo File"
-f "GML"
-f "PostgreSQL"

Plus d’informations sur les commandes ogr2ogr sont référencées sur ce lien. Pour l’import dans PostgreSQL, on a donc :

ogr2ogr -f "PostgreSQL" PG:"host=* port=* schema=* dbname=* user=* password=*" chemin_du_fichier\fichier.geojson

Précisons le nom de la table de destination en ajoutant -nln nom_table, soit :

ogr2ogr -f "PostgreSQL" PG:"host=* port=* schema=* dbname=* user=* password=*" chemin_du_fichier\fichier.geojson -nln table

et le système de projection associé par -a_srs EPSG:4326 . En aparté, comme ogr2ogr permet d’importer de nombreux formats de fichiers, il est ainsi possible de convertir un format de fichier vers l’autre comme transformer un GeoJSON en Shapefile :

ogr2ogr -f "ESRI SHAPEFILE" chemin_du_fichier_destination\fichier.shp chemin_du_fichier_source\fichier.geojson -nln nom_fichier

La donnée spatiale est désormais en base, on va pouvoir “s’amuser” à l’exporter.

2. Création d’un fichier GeoJSON depuis PostgreSQL / PostGIS

2.1. Export avec ogr2ogr

De manière identique à l’import dans PostgreSQL, la librairie ogr2ogr permet d’exporter les données des tables spatiales en différents formats de fichiers.

On commence par exporter une table spatiale en fichier GeoJSON :

ogr2ogr -f "GML" fichier.geojson PG:"host=* port=* schema=* dbname=* user=* password=*" table

D’autres exemples d’exports OGR sont mis à disposition sur le site d’OSGEO.

2.2. Création d’un fichier GeoJSON en PHP

L’idée de ce paragraphe est d’imaginer une interface web permettant à l’utilisateur de générer ses propres fichiers GeoJSON. On s’appuie sur une requête SQL dont le résultat est chargé dans un fichier externe GeoJSON en PHP. La requête a pour objectif de reproduire la structure du format de fichier GeoJSON (cf. $ 1.2.). La fonction json_build_object de PostgreSQL permet de construire un objet JSON facilement. On peut tester la requête directement dans PgAdmin.

SELECT json_build_object(
    'type', 'FeatureCollection',
    'crs',  json_build_object(
        'type',      'name',
        'properties', json_build_object(
        'name', 'EPSG:4326')),
    'features', json_agg(
        json_build_object(
            'type',       'Feature',
            'id',         id,
            'geometry',   ST_AsGeoJSON(wkb_geometry)::json,
            'properties', json_build_object(
                'name', name
            )
        )
    )
) AS objet_geosjon FROM pays;

avec ‘geometry’, la colonne de la géométrie de l’objet géographique et ‘properties’ correspondant aux colonnes de la table ‘pays’ que l’on veut extraire :  ici l’ISO id et le nom du pays name.

Passons maintenant au code PHP qui peut se résumer en trois étapes : connexion à la base de données, exécution de la requête SQL et copie du résultat dans le fichier externe.

On se connecte à la base de données :

try {
	$dbconn=new PDO("pgsql:host=*;port=*;dbname=*","user","password") or die('Connexion impossible');
	$dbconn->exec("SET CHARACTER SET utf8");
	$dbconn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// S'il existe un problème de connection, on obtient le message d'erreur
} catch(PDOException $erreur) {
	$erreur->getMessage(); // Supprimer en production
	echo $erreur;
}

On exécute la requête SQL :

$req=$dbconn->prepare($sql);
$req->execute(); 
$data=$req->fetch();

Enfin, on copie le résultat de la requête dans un fichier externe :

$objet_geosjon=$data['objet_geosjon'];
// Ouverture du fichier en écriture
$fichier = fopen("newfile.geojson", "w") or die("Problème d\'ouverture de fichier");
// Ecriture du résultat de la requête
if(fwrite($fichier, $objet_geosjon)){
	echo "Le fichier GeoJSON a été construit correctement!";
}else{
	echo "Un problème s\'est déroulé lors de l\'écriture du fichier.";
}
// Fermeture du fichier
fclose($fichier);

Voici le code final :

<?php // Connection à la base de données
try {
		$dbconn=new PDO("pgsql:host=*;dbname=*;port=*","user","password") or die('Connexion impossible');
		$dbconn->exec("SET CHARACTER SET utf8");
		$dbconn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// S'il existe un problème de connection, on obtient le message d'erreur
} catch(PDOException $erreur) {
		$erreur->getMessage(); // Supprimer en production
		echo $erreur;
}
if($dbconn){
	// Exécution de la requête SQL
	$sql="SELECT json_build_object(
		'type', 'FeatureCollection',
		'crs',  json_build_object(
			'type',      'name',
			'properties', json_build_object(
			'name', 'EPSG:4326')),
		'features', json_agg(
			json_build_object(
				'type',       'Feature',
				'id',         id,
				'geometry',   ST_AsGeoJSON(wkb_geometry)::json,
				'properties', json_build_object(
					'name', name
				)
			)
		)
	) AS objet_geosjon FROM pays;";
	$req=$dbconn->prepare($sql);
	$req->execute(); 
	$data=$req->fetch();
	if($data){
		$objet_geosjon=$data['objet_geosjon'];
		// Ouverture du fichier en écriture
		$fichier = fopen("pays.geojson", "w") or die("Problème d\'ouverture de fichier");
		// Ecriture du résultat de la requête
		if(fwrite($fichier, $objet_geosjon)){
			echo "Le fichier GeoJSON a été construit correctement!";
		}else{
			echo "Un problème s\'est déroulé lors de l\'écriture du fichier.";
		}
		// Fermeture du fichier
		fclose($fichier);
	}else{
		echo "Un problème s\'est déroulé lors du chargement de la donnée.";
	}
}
?>

Si tout se passe bien, on obtient le fichier GeoJSON avec l’ensemble des objets géographiques extraits de la base de données. On peut vérifier le vecteur en le chargeant dans QGIS.

En conclusion, ce tutoriel nous a montré comment manipuler un fichier GeoJSON qui est un format de données SIG fréquemment utilisé. La librairie ogr2ogr de GDAL nous a permis d’importer et d’exporter le vecteur depuis la base de données PostgreSQL / PostGIS. Ensuite, un script PHP basique a introduit la construction d’une interface web permettant à l’utilisateur de générer un vecteur en format GeoJSON. Ce dernier peut être ensuite traité dans un logiciel SIG de type QGIS ou cartographier en webmapping.

Taggé , , , , , .Mettre en favori le Permaliens.

A propos Florian Delahaye

Fondateur et administrateur du site Geomatick.

2 réponses à PostGIS : Import et création de fichiers GeoJSON à la volée

  1. Michaël DIMECH dit :

    Merci pour ce billet très utile pour mon projet avec le CNAM.
    Je développe ainsi une application web avec Leaflet + PostgreSQL/postGIS. Votre autre billet “Installer PostgreSQL / PostGIS avec Apache et PHP sur Windows” m’a permis de configurer WAMP.

    Cette fois-ci c’est un grand coup de pouce car difficile de trouver l’info de plus en français pour obtenir un objet exploitable par Leaflet d’après les géométries PostGIS créée sous QGIS.

    Je vais regarder plus en profondeur les autres billets 🙂

    MERCI !

  2. Florian Delahaye dit :

    Bonjour Michaël,
    Oui cette méthode permet de s’affranchir de l’installation de serveur cartographique pour les vecteurs. Vous pouvez vous référer à cet article : “Webmapping : Affichage en temps réel de données géographiques depuis PostgreSQL” qui vous sera certainement utile pour votre projet même si l’API utilisée est OpenLayers.
    Je vous remercie pour votre retour, c’est encourageant et n’hésitez pas à faire part de votre projet. Bons développements!

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *