Falsehoods developers believe about GeoJSON


GeoJSON is a lovely, simple format. It’s one of the most important changes in the geospatial world, something that unlocked so much win. A little while ago I wrote a long article about everything about GeoJSON, but want to focus now on a few things that are often forgotten and lead to issues with implementations.

All GeoJSON is wrapped with a FeatureCollection

A lot of GeoJSON implementations will start with the assumption that all GeoJSON input is necessarily in the form of a FeatureCollection, and will optimistically expect features to be an array on the given object. According to the specification, any GeoJSON object can be a root-level object.

A single bare Point geometry is valid GeoJSON

{ "type": "Point", "coordinates": [2, 30] }

And so is a single Feature object

{ "type": "Feature", "properties": { "hello": "Tom" }, "geometry": null }

To quickly band-aid libraries that expect FeatureCollections but advertise ‘GeoJSON support’, I wrote geojson-normalize.

Every feature has a geometry

Usually features in GeoJSON are a combination of geometry and properties: a shape and facts about it.

{ "type": "Feature",
  "properties": {
    "foo": "bar"
  "geometry": {
    "type": "Point",
    "coordinates": [2, 30]

This causes a lot of developers to write code that looks for the type of a feature’s geometry, like

var featureGeometryType = feature.geometry.type;

This is a bug! In both the GeoJSON spec and IETF spec, the geometry member of a feature can be null. Features don’t need to have geometry.

All GeoJSON is WGS84

This is something that changes between the current GeoJSON specification and IETF standard: the GeoJSON maintainers wisely decided to remove the ability to define GeoJSON in alternative projections. But until everyone follows the IETF specification:

GeoJSON actually does, for now, support projected data!

{ "type": "Feature",
  "properties": {},
  "geometry": {
    "type": "Point",
    "coordinates": [2, 42]
  "crs": {
    "type": "name",
    "properties": {
      "name": "EPSG:28191"
    } } }

Footnote tangent

Accessing feature.geometry.type in GeoJSON is risky, since you’re trying to look two layers into an object, and the second layer, feature.geometry, can be null. From using optionals, maybe types, and existential operators in Swift, Elm, and CoffeeScript, this JavaScript gotcha seems more and more preventable.

In Swift, for instance, you could write this idiomatic code that sidesteps the null (nil) issue:

if let geometryType = feature.geometry?.type {
    print("The geometry is a \(geometryType)")
} else {
    print("No geometry object.")

In Elm, you could write

getGeometryType feature =
    case feature of
        Just value ->
        Nothing ->

Fantasy Land gets us partially the way. There’s also an interesting discussion about the existential operator in JavaScript.

Footnote footnotes

Posted Jun 05, 2016 Tweet / Follow me on Twitter

Tom MacWright

I'm . I work on tools for creativity at Mapbox. This is where I write about technology and everything else.