GeoJSON
geografi skriven som JSON
Vad det är
GeoJSON är ett öppet format för att utbyta kartobjekt, alltså en kartas punkter, linjer och ytor tillsammans med uppgifterna som hör till dem, som ett enda vanligt JSON-dokument. IETF standardiserade det som RFC 7946 i augusti 2016, och det ersatte då den specifikation från användargemenskapen som först publicerades 2008. En GeoJSON-text skickas med medietypen application/geo+json och sparas oftast med filändelsen .geojson, även om vanlig .json också är registrerad.
Formatet har tre sorters objekt, och vart och ett anger sin sort i fältet type.
- Geometry är en form. Det finns sju typer: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon och GeometryCollection. Det är formerna i Simple Features-modellen från Open Geospatial Consortium (OGC), samma former som kodningarna WKT och WKB bär i text och binärt.
- Feature är en sak på kartan: en geometri, ett objekt i fältet
propertiesmed sakens attribut och ett valfrittid. Geometrin får vara null för ett objekt vars plats är okänd. - FeatureCollection håller en lista med objekt i fältet
features. Det är vad de flesta filer och API-svar innehåller.
Ett enskilt objekt för en smart elmätare ser ut så här:
{
"type": "Feature",
"id": "meter-0417",
"geometry": {
"type": "Point",
"coordinates": [12.5683, 55.6761]
},
"properties": {
"name": "Meter 417",
"installed": "2023-04-12"
}
}
Varje position är en array av tal: longitud först, sedan latitud och sist en valfri höjd i meter.
Specifikationen säger att de två första kommer ”precis i den ordningen”, så punkten ovan ligger i
centrala Köpenhamn, 12,57 grader öst och 55,68 grader nord. Alla koordinater använder ett och samma
referenssystem, longitud och latitud enligt WGS 84 i decimalgrader, som OGC betecknar CRS84.
Versionen från 2008 lät en fil namnge ett annat system i fältet crs. RFC 7946 tog bort fältet
eftersom blandade referenssystem hade skapat problem med interoperabiliteten, och standarden
tillåter ett annat system bara där alla parter har kommit överens om det i förväg.
Polygoner har egna regler. Varje ring är sluten, med minst fyra positioner där den sista upprepar den första. Den första ringen är den yttre gränsen, och eventuella senare ringar är hål. RFC 7946 lägger till en högerhandsregel, där yttre ringar går moturs och hål medurs. Eftersom versionen från 2008 inte sa något om varvriktning ska en parser ändå godta polygoner som bryter mot regeln.
Varför det spelar roll
Allt som kan läsa JSON kan läsa GeoJSON. En webbläsare tolkar det utan insticksprogram, ett bibliotek för webbkartor ritar det direkt och en dokumentdatabas lagrar det som det är. RFC 7946 nämner bibliotek för webbkartor i JavaScript, JSON-baserade dokumentdatabaser och webb-API:er som de ställen där formatet används brett. Den räckvidden gör GeoJSON till det givna formatet när kartdata lämnar ett GIS på skrivbordet för att hamna på en webbsida eller i ett API.
Standarder bygger också på det. OGC API – Features, OGC:s standard för att servera geografiska objekt över HTTP, rekommenderar GeoJSON överallt där data går att uttrycka i det. En server som erbjuder GeoJSON returnerar en FeatureCollection för en lista med objekt och en enskild Feature för ett objekt, båda som application/geo+json, och dess förvalda referenssystem är samma longitud och latitud enligt WGS 84 som GeoJSON låser fast.
Samma designval sätter också gränserna.
- Ett enda referenssystem. Data som lagras i ett nationellt plant koordinatsystem måste transformeras till longitud och latitud innan de skrivs, och transformeras tillbaka av varje mottagare som mäter i meter.
- Bara enkla former. Geometrityperna täcker punkter, linjer med raka segment och polygoner. Kurvor, solider som 3D-modeller av städer och koordinater utanför WGS 84 faller utanför formatet, och OGC API – Features ger just de fallen som exempel på data som GeoJSON inte kan bära.
- Storlek. Varje koordinat skrivs ut som decimalsiffror, och en FeatureCollection är ett enda JSON-värde, som en vanlig JSON-parser läser till sista byte innan den lämnar ifrån sig något av objekten. RFC 8142 definierar GeoJSON Text Sequences, med medietypen application/geo+json-seq och en GeoJSON-text per post, så att godtyckligt stora dataset kan läsas stegvis.
- Varje gräns lagras två gånger. Två angränsande polygoner bär var sin fullständig kopia av den gemensamma gränsen, och en ändring i den ena kopian kan öppna en glipa eller ett överlapp.
RFC 7946 säger också rakt ut vad formatet lämnar åt andra. GeoJSON har inget eget integritetsskydd och inget eget skydd mot att data ändras, så data under överföring förlitar sig på TLS. Avsnittet om säkerhet varnar för att publicerade platser för utsatta personer, djur, livsmiljöer eller anläggningar kan utsätta dem för spårning eller skada, och för att suddiga positioner i ett anonymiserat dataset knappast står emot en målmedveten attack.
Så ser det ut i praktiken
I mer än trettio GIS-projekt som byggdes, driftsattes och fick support i produktion var GeoJSON ett av formaten som GDAL/OGR flyttade data mellan, tillsammans med shapefiler, GeoTIFF, KML och vektortiles. Geodatan hade sitt hem i PostgreSQL med PostGIS, dataarbetet gjordes i QGIS och JOSM, och frontenden bestod av webbkartor byggda på Mapbox GL och Leaflet.
Innan något av det kan börja måste referenssystemet vara bestämt. Vid en migrering från MSSQL till PostgreSQL med tillägget PostGIS gick över 50 miljoner spatiala poster genom ETL-pipelines vars transformeringssteg anpassade dem till SRID-standarden EPSG:4326. Den koden betecknar samma geodetiska datum, WGS 84 i grader, som GeoJSON låser fast. PostGIS-manualen anger att utdata från funktionen ST_AsGeoJSON följer RFC 7946 för geometri i EPSG:4326, utan att någon transformering behövs.
Var det går fel
Punkterna hamnar i fel hav. Ett lager med danska adresser dyker upp mitt i Arabiska havet, och varje intervallkontroll går ändå igenom eftersom båda talen är giltiga grader. Latitud och longitud byttes på vägen in. EPSG:4326 listar formellt latitud före longitud, många datakällor följer det, och GeoJSON vill ha longituden först. Bygg varje position från namngivna fält i stället för från kolumnordningen, och håll ett testobjekt på en känd adress, så att en förväxling fäller ett test i stället för att upptäckas när någon granskar kartan.
Koordinaterna kommer i meter. Ett lager syns inte på kartan eller avvisas av klienten, och
filen innehåller koordinater i hundratusental där det borde stå grader. Geometrin var lagrad i ett
projicerat nationellt koordinatsystem och exporterades som den var. Transformera den till longitud
och latitud först, med ST_Transform(geom, 4326) i PostGIS. Står geometrin kvar otransformerad
lägger ST_AsGeoJSON som standard till ett fält crs, just det fält som RFC 7946 tog bort.
Polygonerna ritas inverterade i en klient. Ett serviceområde fyller hela kartan utom sin egen
form, medan andra verktyg ritar samma fil korrekt. Klienten använder varje rings riktning för att
skilja insida från utsida, och ringarna går åt andra hållet, vilket versionen från 2008 tillät.
PostGIS-manualen noterar att vissa klienter kräver högerhandsregeln, så tillämpa den före export med
ST_ForcePolygonCCW(geom), och testa resultatet i varje klient som läser det.
Filerna bär fler decimaler än kartan behöver. Ett lager med detaljerade polygoner tar sekunder
att ladda ner på en telefon, och koordinaterna har nio eller fler decimaler. ST_AsGeoJSON skriver
som standard upp till nio decimaler. RFC 7946 påpekar att steget från sex till femton decimaler
nästan kan fördubbla en texts storlek, medan sex redan räcker för ungefär 10 centimeter. Ange ett
mindre maxdecimaldigits, och minska först precisionen med ST_ReducePrecision, eftersom
PostGIS-manualen varnar för att en geometri kan bli ogiltig om man bara kapar siffror i utdata.
Interna kolumner följer med i properties. En publik slutpunkt returnerar ägarnamn,
kostnadsuppgifter eller anteckningar som var tänkta att stanna i databasen. När ST_AsGeoJSON får en
hel rad lägger funktionen varje kolumn utom geometrin i properties. Välj i en delfråga bara de
kolumner som är avsedda för publicering, och namnge på PostGIS 3.5 eller senare nyckelkolumnen så
att 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;
Läs mer
- RFC 7946: The GeoJSON Format — IETF-standarden, med objekttyperna, koordinatordningen, regeln för varvriktning, råden om precision och avsnittet om säkerhet.
- RFC 8142: GeoJSON Text Sequences — systerformatet som delar upp ett stort dataset i en GeoJSON-text per post.
- ST_AsGeoJSON — sidan i PostGIS-manualen om att exportera geometrier och hela rader som GeoJSON, med alternativen för precision och flaggor.
- EPSG:4326 WGS 84 — posten i registret vars axelordning sätter latituden först, tvärtemot GeoJSON.
- OGC API – Features – Part 1: Core — OGC-standarden som rekommenderar GeoJSON för att servera geografiska objekt över HTTP.