GeoJSON
geografi skrevet som JSON
Hva det er
GeoJSON er et åpent format for å utveksle kartobjekter, altså punktene, linjene og flatene på et kart sammen med opplysningene som hører til dem, som ett vanlig JSON-dokument. IETF standardiserte det som RFC 7946 i august 2016, og den erstattet fellesskapsspesifikasjonen som først kom ut i 2008. En GeoJSON-tekst sendes med medietypen application/geo+json og lagres som regel med filendelsen .geojson, selv om vanlig .json også er registrert.
Formatet har tre slags objekter, og hvert av dem oppgir hvilken slags det er, i et «type»-medlem.
- Geometry er en form. Det finnes sju typer: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon og GeometryCollection. De er formene i Simple Features-modellen fra Open Geospatial Consortium (OGC), de samme som kodingene WKT og WKB bærer som tekst og binært.
- Feature er én ting på kartet: en geometri, et «properties»-objekt med egenskapene til tingen, og en valgfri «id». Geometrien kan være null for et objekt der plasseringen ikke er kjent.
- FeatureCollection samler en liste med objekter i et «features»-medlem. Det er dette de fleste filer og API-svar inneholder.
Ett enkelt objekt for en smart strømmåler ser slik ut:
{
"type": "Feature",
"id": "meter-0417",
"geometry": {
"type": "Point",
"coordinates": [12.5683, 55.6761]
},
"properties": {
"name": "Meter 417",
"installed": "2023-04-12"
}
}
Hver posisjon er en liste med tall: lengdegrad først, så breddegrad, så en valgfri høyde i meter. Spesifikasjonen sier at de to første kommer «precisely in that order», nøyaktig i den rekkefølgen, så punktet ovenfor ligger i sentrum av København, 12,57 grader øst og 55,68 grader nord. Alle koordinater bruker ett og samme referansesystem, lengde- og breddegrad i WGS 84 oppgitt i desimalgrader, som OGC kaller CRS84. Versjonen fra 2008 lot en fil oppgi et annet system i et «crs»-medlem. RFC 7946 fjernet det medlemmet fordi blandede referansesystemer hadde skapt problemer med samspillet mellom systemer, og tillater et annet system bare der alle parter har blitt enige om det på forhånd.
Polygoner har egne regler. Hver ring er lukket, med minst fire posisjoner, og den siste gjentar den første. Den første ringen er yttergrensen, og eventuelle senere ringer er hull. RFC 7946 legger til en høyrehåndsregel, der ytre ringer går mot klokka og hull med klokka, men fordi versjonen fra 2008 ikke sa noe om retningen, får parsere beskjed om å godta polygoner som bryter regelen.
Hvorfor det er viktig
Alt som leser JSON, kan lese GeoJSON. En nettleser tolker det uten noe tillegg, et bibliotek for webkart tegner det direkte, og en dokumentdatabase lagrer det slik det er. RFC 7946 nevner JavaScript-biblioteker for webkart, JSON-baserte dokumentdatabaser og web-API-er som stedene der det er i utstrakt bruk. Den rekkevidden gjør det til det vanlige formatet når kartdata forlater et GIS-verktøy på skrivebordet og skal ut på en nettside eller gjennom et API.
Standarder bygger også på det. OGC API – Features, OGC-standarden for å servere geografiske objekter over HTTP, anbefaler GeoJSON overalt der dataene kan uttrykkes i det. En server som tilbyr GeoJSON, returnerer en FeatureCollection for en liste med objekter og en enkelt Feature for ett objekt, begge som application/geo+json, og standardsystemet er den samme lengde- og breddegraden i WGS 84 som GeoJSON låser fast.
De samme designvalgene setter grensene.
- Ett referansesystem. Data som ligger i et nasjonalt rutenett, må transformeres til lengde- og breddegrad før de skrives, og transformeres tilbake av hver mottaker som måler i meter.
- Bare enkle former. Geometritypene dekker punkter, rette linjestykker og polygoner. Kurver, volumer som 3D-bymodeller og koordinater utenfor WGS 84 faller utenfor formatet, og OGC API – Features bruker nettopp de tilfellene som eksempler på data GeoJSON ikke kan bære.
- Størrelse. Hver koordinat skrives ut som desimalsifre, og en FeatureCollection er én enkelt JSON-verdi, som en vanlig JSON-parser leser helt til siste byte før den gir fra seg et eneste objekt. RFC 8142 definerer GeoJSON Text Sequences, med medietypen application/geo+json-seq og én GeoJSON-tekst per post, slik at vilkårlig store datasett kan leses bit for bit.
- Felles kanter lagres dobbelt. To nabopolygoner lagrer hver sin fulle kopi av grensen de deler, så grensen står der to ganger, og en endring i den ene kopien kan åpne en glipe eller en overlapp.
RFC 7946 sier også rett ut hva formatet overlater til andre. GeoJSON gir ingen beskyttelse av personvern eller integritet på egen hånd, så data under overføring er avhengige av TLS. Sikkerhetsavsnittet advarer om at å publisere plasseringen til sårbare personer, dyr, leveområder eller anlegg kan utsette dem for sporing eller skade, og at å gjøre posisjonene uskarpe i et anonymisert datasett neppe stopper et målrettet angrep.
Slik ser det ut i praksis
På tvers av mer enn tretti GIS-prosjekter som ble bygget, satt i produksjon og driftet var GeoJSON ett av formatene GDAL/OGR flyttet data mellom, sammen med shapefiler, GeoTIFF, KML og vektorfliser. PostgreSQL med PostGIS holdt de romlige dataene under det hele, QGIS og JOSM tok seg av selve dataarbeidet, og det brukerne så, var webkart bygget på Mapbox GL og Leaflet.
Referansesystemet må være avklart før noe av dette. I en migrering fra MSSQL til PostgreSQL med PostGIS-utvidelsen gikk over 50 millioner romlige poster gjennom ETL-pipelines der transformasjonssteg brakte dem over på SRID-standarden EPSG:4326. Den koden betegner det samme WGS 84-datumet i grader som GeoJSON låser fast, og PostGIS-manualen slår fast at utdataene fra funksjonen ST_AsGeoJSON følger RFC 7946 for geometri i EPSG:4326, uten at noen transformasjon trengs.
Hvor det går galt
Punktene havner i feil hav. Et lag med adresser i Oslo dukker opp midt i Arabiahavet, og hver kontroll av verdiområdet går likevel gjennom, fordi begge tallene er gyldige grader. Bredde- og lengdegrad ble byttet om på vei inn. EPSG:4326 oppgir formelt breddegraden før lengdegraden, mange datakilder følger det, og GeoJSON vil ha lengdegraden først. Bygg hver posisjon fra navngitte felter i stedet for fra kolonnerekkefølgen, og ha et testobjekt på en kjent adresse, slik at en ombytting stopper i en test og ikke først i en gjennomgang av kartet.
Koordinatene kommer i meter. Et lag mangler på kartet eller blir avvist av klienten, og filen
inneholder koordinater i hundretusenvis der det skulle stått grader. Geometrien var lagret i et
projisert nasjonalt rutenett og ble eksportert som den var. Transformer den til lengde- og
breddegrad først, med ST_Transform(geom, 4326) i PostGIS. Får den stå utransformert, legger
ST_AsGeoJSON som standard til et «crs»-medlem, nettopp det medlemmet RFC 7946 fjernet.
Polygonene tegnes vrengt i én klient. Et dekningsområde fyller hele kartet unntatt sin egen
form, mens andre verktøy tegner den samme filen riktig. Den klienten bruker retningen på hver ring
til å skille innsiden fra utsiden, og ringene går motsatt vei, noe versjonen fra 2008 tillot.
PostGIS-manualen påpeker at enkelte klienter krever høyrehåndsregelen, så bruk den før eksporten med
ST_ForcePolygonCCW(geom), og test resultatet i hver klient som leser det.
Filene har flere sifre enn kartet trenger. Et lag med detaljerte polygoner bruker flere sekunder
på å lastes ned på en telefon, og koordinatene har ni eller flere desimaler. ST_AsGeoJSON skriver
som standard opptil ni desimaler, og RFC 7946 påpeker at å gå fra seks til femten kan nesten doble
størrelsen på en tekst, mens seks allerede gir en oppløsning på omtrent 10 centimeter. Gi en lavere
maxdecimaldigits, og reduser presisjonen med ST_ReducePrecision først, fordi PostGIS-manualen
advarer om at å kutte sifre bare i utdataene kan gjøre en geometri ugyldig.
Interne kolonner følger med i properties. Et offentlig endepunkt returnerer eiernavn, kosttall eller notater som skulle blitt i databasen. Får ST_AsGeoJSON en hel rad, legger den hver kolonne unntatt geometrien i «properties». Velg bare kolonnene som skal publiseres, i en underspørring, og på PostGIS 3.5 eller nyere navngir du nøkkelkolonnen, slik at den blir objektets «id»:
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(ST_AsGeoJSON(m.*, id_column => 'id')::json)
)
FROM (SELECT id, name, geom FROM meters) AS m;
Les mer
- RFC 7946: The GeoJSON Format — IETF-standarden, med objekttypene, koordinatrekkefølgen, regelen for ringretning, rådene om presisjon og sikkerhetsavsnittet.
- RFC 8142: GeoJSON Text Sequences — følgeformatet som deler et stort datasett opp i én GeoJSON-tekst per post.
- ST_AsGeoJSON — siden i PostGIS-manualen om å eksportere geometri og hele rader som GeoJSON, med valgene for presisjon og flagg.
- EPSG:4326 WGS 84 — registeroppføringen der aksefølgen setter breddegraden først, stikk motsatt av GeoJSON.
- OGC API – Features – Part 1: Core — OGC-standarden som anbefaler GeoJSON for å servere objekter over HTTP.