Introduction to GeoJSON
Tags: geodata, gis, geojson
Published: 2023-02-13 00:08:46

---
title: Introduction to GeoJSON
published: true
date: 2023-02-10 00:00:00 UTC
tags: Geodata, gis, geojson
canonical_url: https://imfeld.dev/writing/introduction_to_geojson
---

Geographic data is ubiquitous in our lives. It is found in small applications like planning a vacation, and in complex worldwide topics such as population health and demographic studies. While the terms and systems involved may seem daunting at first, understanding geographic data can open up a lot of possibilities for visualizing and understanding the world.

Nearly every web application that works with geographic data uses represents it as GeoJSON. This is a short overview of GeoJSON and its structure to help make more sense of it.

In later articles in this series, I'll cover more interesting things you can do with geographic data and how to actually work with it, but this will provide a good foundation to build upon.

As the name implies, GeoJSON is just a format for representing geographic data as JSON. It defines six types of geometries, and a few different containers that group them together or provide extra information.

All images below are from [geojson.io](https://geojson.io/), a great tool for playing with and visualizing GeoJSON.

## Points and Positions 

The simplest geometry is the `Point`. Points are commonly used to indicate places of interest and other markers on maps where you just want to show the location, and don't need an area or boundary.

A Point contains just a single position. In GeoJSON, a "position" is an array with two numbers: the longitude and the latitude, in that order.

You may be accustomed to the more common "latitude first, longitude second" ordering. This is a common source of confusion when getting started, so it helps to think in terms of `[x, y]` coordinates instead.

A position array may have a third value to represent elevation, but this is usually omitted unless the application requires it.

Every GeoJSON geometry has a `type` field indicating what type of geometry it is, and a `coordinates` field that defines the shape itself. A point representing a random location in southern Australia looks like this:

```json
{
  "type": "Point",
  "coordinates": [137.2, -32]
}

```

![geojson-point.jpeg](https://images.imfeld.dev/blog/geojson-point_1676017854016_0-w650-AYY6cyE0zHs99aPDwux8kA.jpg)

You may also place multiple points into a single geometry using the `MultiPoint` type. In this case, the coordinates are an array of positions.

```json
{
  "type": "MultiPoint",
  "coordinates": [
    [137.2, -32],
    [133.1, -30]
  ]
}

```

![geojson-multipoint.jpeg](https://images.imfeld.dev/blog/geojson-multipoint_1676017913216_0-w650-AYY6dTadl78pqLFhnfsIbg.jpg)

`MultiPoint` should only be used when the set of points are conceivably actually part of the same object. There are better ways to represent multiple, independent points, which I'll cover later.

## Lines 

The `LineString` is useful when drawing lines on the map, such as when suggesting a route between two places. It contains a set of points that join together, connect-the-dots style, to form a line. As with `MultiPoint`, it contains an array of positions, but a valid `LineString` must contain at least two positions.

```json
{
  "type": "LineString",
  "coordinates": [
    [-46.64, -23.577],
    [-43.2, -22.9],
    [-43.94, -19.89]
  ]
}

```

GeoJSON also provides the `MultiLineString` type, which represents a set of related lines. Its coordinates are an array of `LineString` coordinates, with each array member drawing a single line.

Although the lines are considered part of the same geometry, they are not connected together.

```json
{
  "type": "MultiLineString",
  "coordinates": [
    [
      [-46.64, -23.577],
	  [-43.2, -22.9],
      [-43.94, -19.89]
    ],
    [
      [-48.18, -21.77],
      [-47.46, -20.58],
      [-46.57, -21.78]
    ]
  ]
}

```

![geojson-multilinepoint.jpeg](https://images.imfeld.dev/blog/geojson-multilinepoint_1676019339259_0-w650-AYY6iZSUno63fEt6GHuw3g.jpg)

## Making Geometries More Useful 

A geometry on its own is just a shape, with no way to attach any other information to it. GeoJSON solves this with the `Feature` type, which wraps a geometry and allows you add any metadata you want.

```json
{
  "type": "Feature",
  "id": "marker-001",
  "properties": {
    "name": "My favorite place",
    "icon": "star",
    "rating": "a billion"
  },
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [-46.64, -23.577],
      [-43.2, -22.9],
      [-43.94, -19.89]
    ]
  }
}

```

The `id` property is optional but can be useful for linking a `Feature` back to a particular object in a database, or something similar.

There is no defined schema for `properties` — you can put any JSON object inside there.

## Groups of Objects 

A `FeatureCollection` allows you to group multiple `Feature` objects together in a single object.

```json
{
  "type": "FeatureCollection",
  "features": [
    { 
      "type": "Feature", 
      "properties": { 
        "name":"my house"
      }, 
      "geometry": { 
      	"type": "Point",
        "coordinates": [1, 2]
      } 
    },
    // And so on....
    { "type": "Feature", "properties": { }, "geometry": { } }
  ]
}

```

The `GeometryCollection` type is similar, but for raw geometries instead of `Feature`. You probably won't encounter `GeometryCollection` often. Usually, one of the "Multi" objects or a `FeatureCollection` is a better fit, but it's good to know about.

```json
{
  "type": "GeometryCollection",
  "geometries": [
    { "type": "Point", "coordinates": [0, 51.5] },
    { 
      "type": "LineString",
      "coordinates": [
        [0, 51.5],
        [1.55, 50.7],
        [2.35, 48.85]
      ]
    }
  ]
}

```

![geojson-geometrycollection.jpeg](https://images.imfeld.dev/blog/geojson-geometrycollection_1676018882698_0-w650-AYY6gp6_mUDvFAOHUPtGKQ.jpg)

## Polygons 

The `Polygon` is commonly used to draw boundaries around geographic regions or other areas. This is one of the most used geometries in GeoJSON, but they do add additional complexity.

Unlike a `LineString`, a `Polygon` must be explicitly closed. That is, the first and last points in the `Polygon` must be identical for it to be valid.

Furthermore, the points in a `Polygon` must be in counterclockwise order. This rule makes it easier for renderers to figure out which side of the polygon is the outside vs. the inside, without needing to do additional calculations.

There is no limit on the number of segments in a polygon. It can be as simple as a triangle or complex enough to follow the contours of a shoreline.

The last `LineString` above would be represented like this:

```json
{ 
  "type": "Polygon",
  "coordinates": [
    [
      [0, 51.5],
      [2.35, 48.85],
      [1.55, 50.7],
      [0, 51.5]
    ]
  ]
}

```

![geojson-simplepolygon.jpeg](https://images.imfeld.dev/blog/geojson-simplepolygon_1676081330066_0-w650-AYY-O31TUBkHVmxcvshijg.jpg)

You'll note that although there's just a single shape here, the array nesting looks more like a `MultiLineString`. This is because `Polygon` allows you to specify holes inside the shape as well.

The below `Polygon` is a square with two smaller square holes inside it. The first entry represents the outer ring that gives the overall shape, and the other entries define the holes inside the polygon.

```json
{
  "type": "Polygon",
  "coordinates": [
    [
      [25, -23],
      [25, -28],
      [30, -28],
      [30, -23],
      [25, -23]
    ],
    [
      [26, -24],
      [27, -24],
      [27, -25],
      [26, -25],
      [26, -24]         
    ],
    [
      [28, -26],
      [29, -26],
      [29, -25],
      [28, -25],
      [28, -26]
    ]
  ]
}

```

![geojson-polygonholes.jpeg](https://images.imfeld.dev/blog/geojson-polygonholes_1676081519094_0-w650-AYY-Pl-Y7AJDZfJVLDhtCQ.jpg)

While the outer ring of the `Polygon` has its points in counterclockwise order, the inner holes' points must be in clockwise order, which again helps renderers to determine which side of the edge is inside the polygon.

Ensuring that the points are in the correct order may seem difficult, but geometry libraries generally handle this for you. They also provide functions such as [turf's rewind](http://turfjs.org/docs/#rewind) or [PostGIS's ST\_ForcePolygonCCW](https://postgis.net/docs/ST_ForcePolygonCCW.html), which will take a polygon and "fix" the point order so that the outer line is counterclockwise and the inner ones are clockwise.

## MultiPolygons 

By now you can probably guess what a `MultiPolygon` is. These are very useful in representing geographic regions such as the state of Michigan or anything with islands, which can't be represented as a single contiguous shape.

It starts to get hard to read with all the nested arrays, but the coordinates for a `MultiPolygon` is just an array of `Polygon` coordinates. This example shows a `MultiPolygon` that contains two polygons — the square with holes from above, and a simple triangle.

```json
{
  "type": "MultiPolygon",
  "coordinates": [
    [
      [
        [25, -23],
        [25, -28],
        [30, -28],
        [30, -23],
        [25, -23]
      ],
      [
        [26, -24],
        [27, -24],
        [27, -25],
        [26, -25],
        [26, -24]         
      ],
      [
        [28, -26],
        [29, -26],
        [29, -25],
        [28, -25],
        [28, -26]
      ]
    ],

    [
      [
        [28.5, -28.2],
        [25.1, -30],
        [30.2, -31.2],
        [28.5, -28.2]
      ]
    ]
  ]
}

```

![geojson-multipolygon.jpeg](https://images.imfeld.dev/blog/geojson-multipolygon_1676081931304_0-w650-AYY-RKhwfcEWOoItPDKUKw.jpg)

## Summing Up 

That covers all the different types of objects that you can create in GeoJSON. In future articles in this series, we'll look more into actually processing data and working with these objects in real applications.