What Is GeoJSON? Format, Structure, and Every Geometry Type
June 1, 2026
GeoJSON is an open standard (RFC 7946) for representing geographic features as JSON. In practice a GeoJSON file is one FeatureCollection: an array of Feature objects, where each Feature pairs a geometry (a point, a line, or a polygon) with a free-form properties object. Every coordinate is written as [longitude, latitude] in the WGS84 reference system. This post walks the whole structure with real JSON.
The three things a GeoJSON object can be
Every object has a type member. At the top level it is one of three kinds, nested inside each other like Russian dolls:
- Geometry: shape and coordinates only (for example a
Point). No attributes. - Feature: one geometry plus a
propertiesobject for attributes, plus an optionalid. - FeatureCollection: an array of Features. This is the whole file in most exports.
Here is the smallest complete file: a FeatureCollection holding one point Feature.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-122.4194, 37.7749]
},
"properties": {
"name": "Rally Point"
}
}
]
}Coordinate order: longitude first
The atomic unit in GeoJSON is a position: an array of numbers in the order [longitude, latitude], with an optional third value for altitude or elevation in meters.
[-122.4194, 37.7749] // longitude, latitude
[-122.4194, 37.7749, 16] // longitude, latitude, elevation (m)This trips up almost everyone, because we say and write coordinates as latitude, longitude (a GPS readout, a Google Maps URL, an MGRS conversion). GeoJSON reverses that. If your points land in the ocean off West Africa near 0, 0, you have almost certainly swapped the pair. The reference system is fixed to WGS84 (EPSG:4326); RFC 7946 removed the old crs member, so you cannot declare a different projection. Reproject to WGS84 before writing GeoJSON.
The seven geometry types
GeoJSON defines six concrete geometries plus a collection. The coordinate nesting deepens by one array level each step: a position, an array of positions, an array of those, and so on.
| type | coordinates shape | Represents |
|---|---|---|
| Point | [x, y] | A single location |
| LineString | [[x, y], ...] | A path of 2+ points |
| Polygon | [[[x, y], ...]] | An area, with optional holes |
| MultiPoint | [[x, y], ...] | Many points, one feature |
| MultiLineString | [[[x, y], ...], ...] | Many paths, one feature |
| MultiPolygon | [[[[x, y], ...]], ...] | Many areas, one feature |
| GeometryCollection | geometries[] | Mixed geometries together |
Point and LineString
A Point is one position. A LineString is an array of two or more positions, drawn in order.
{ "type": "Point", "coordinates": [-122.42, 37.77] }
{
"type": "LineString",
"coordinates": [
[-122.42, 37.77],
[-122.41, 37.78],
[-122.40, 37.78]
]
}Polygon: rings, holes, and the closing rule
A Polygon is an array of linear rings. The first ring is the outer boundary; any further rings are holes cut out of it. A linear ring has two hard rules:
- It must be closed: the last position equals the first, so a triangle has four positions, not three.
- Per RFC 7946 it follows the right-hand rule: the exterior ring runs counterclockwise, holes run clockwise. Many parsers are lenient about this, but writing it correctly avoids rendering and area-sign surprises.
{
"type": "Polygon",
"coordinates": [
[
[-122.43, 37.77],
[-122.40, 37.77],
[-122.40, 37.79],
[-122.43, 37.79],
[-122.43, 37.77]
]
]
}The Multi variants and GeometryCollection
Each Multi type is just one array level deeper, letting a single feature hold several disjoint shapes (an archipelago as one MultiPolygon, a broken trail as one MultiLineString). A GeometryCollection is the escape hatch: it holds a geometries array of mixed types and has no single coordinates member of its own.
{
"type": "GeometryCollection",
"geometries": [
{ "type": "Point", "coordinates": [-122.42, 37.77] },
{
"type": "LineString",
"coordinates": [[-122.42, 37.77], [-122.40, 37.78]]
}
]
}The Feature object: geometry plus properties
A bare geometry carries no name, color, or description. A Feature fixes that by wrapping exactly one geometry and attaching a properties object. The spec puts no constraints on properties: it is any JSON object you like, or null. An optional top-level id identifies the feature.
{
"type": "Feature",
"id": "wp-12",
"geometry": {
"type": "Point",
"coordinates": [-122.4194, 37.7749, 16]
},
"properties": {
"name": "Rally Point",
"color": "#f59e0b",
"elevation": 16
}
}The spec deliberately does not standardize styling, so keys like color or width are a convention between the tool that writes them and the tool that reads them. A reader that does not know a key simply ignores it and still gets valid geometry. That is the quiet strength of the format: extra keys never break it.
The bbox member
Any GeoJSON object may carry an optional bbox: a flat array giving the bounding box as [west, south, east, north] (the all-axes minimums followed by the all-axes maximums). It lets a consumer zoom to the data without scanning every coordinate first.
{
"type": "FeatureCollection",
"bbox": [-122.43, 37.77, -122.40, 37.79],
"features": [ /* ... */ ]
}Gotchas worth memorizing
- Order is lng, lat. Not lat, lng. This is the number-one bug.
- WGS84 only. No projected coordinates, no
crsmember. Reproject first. - Rings must close. First position equals last; a ring needs at least four positions.
- Winding matters. Exterior counterclockwise, holes clockwise (the right-hand rule).
- Mind the antimeridian. RFC 7946 advises splitting geometries that cross 180 degrees longitude into a Multi geometry, rather than letting a line wrap the globe.
- properties can be null. A Feature is still valid with no attributes.
A real export
Put it together and a route plus a waypoint exported from a map looks like one FeatureCollection: a LineString for the route, a Point for the marker, each with its own properties.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [[-122.42, 37.77], [-122.41, 37.78]]
},
"properties": { "kind": "route", "name": "Approach", "lineColor": "#e11d48" }
},
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-122.41, 37.78] },
"properties": { "kind": "waypoint", "name": "RV 1" }
}
]
}That is exactly the shape MapGridder writes when you export. Waypoints and symbols become Points, routes and measurements become LineStrings, polygons and rings become Polygons, and the styling rides along in properties.
FAQ
Is GeoJSON the same as JSON?
GeoJSON is a specific schema written in JSON. Every GeoJSON file is valid JSON, but only files that follow the RFC 7946 structure (type members, geometries, coordinate arrays) are valid GeoJSON.
What coordinate order does GeoJSON use?
Longitude first, then latitude, with an optional third altitude value: [longitude, latitude, altitude]. It is the reverse of how coordinates are normally spoken or written.
Can GeoJSON use a projection other than WGS84?
No. RFC 7946 fixes the system to WGS84 longitude and latitude and removed the crs member from earlier drafts. Reproject other data to WGS84 before exporting to GeoJSON.
How many points does a polygon ring need?
At least four positions, because the ring must close: the last position repeats the first. So a triangle is written as four positions, not three.
How do I create a GeoJSON file?
Write it by hand for small data, generate it in code, or export it from a map tool. See the guide to exporting a map to GeoJSON.
Want a GeoJSON file without writing one by hand? Export a map to GeoJSON in MapGridder, or open the map and start placing data.