Hands On

An Introduction to GeoJSON

By Raymond Camden | 04 September 2019

As a new developer evangelist at HERE, I’m trying to quickly come to speed with geographic and map related terms and technologies. One of them I discovered rather quickly is a fascinating (and simple!) specification called GeoJSON.

As you guess, GeoJSON is JSON related, which is great because if I never see XML again I’ll die a happy developer. Before I dig into what GeoJSON does and what problems it solves, be sure to check out the website (https://geojson.org) and full specification (https://tools.ietf.org/html/rfc7946). And by the way, definitely take a look at that specification. I spent most of my life thinking those specs were boring, mind numbing technical documents but they can actually be quite helpful. In this particular case there were a few questions I had that were answered in the spec so it was absolutely worth my time reading it!

GeoJSON is Geographic Data

At a high level, GeoJSON is a way of representing geographic data. Let’s say you have a collection of cats (a… catalog let’s say) and the location of each cat is something you want to work with. That could be displaying them on a map, or telling a user which cat is closer to them, it doesn’t really matter.

The previous example was focused on “points”, i.e. exact locations of cats, but that’s not the only type of data that can be represented in GeoJSON. Imagine you kept track of a cat’s movement through the data. That movement could be represented as a path over different points and stored in GeoJSON.

As yet another example, as we know cats are very territorial. You could represent a set of cats and their territories as a set of polygons. Anything inside that polygon represents the area that belongs to the cat. (And yes, it belongs to the cat, not you.)

If you can imagine every different way you can use a map or a globe, GeoJSON supports representing that information. Even better, the specification supports any ad hoq data as well. If we go back to the imaginary list of cats and their locations, we can associate the cats name, breed, gender, and so forth along with the geographic data.

GeoJSON Parts

GeoJSON consists of the following different parts:

  • Geometry object: This is either the point, line, or polygon described earlier. Basically the location information.
  • Feature object: This is the geometry object and the associated random ad hoq data. Remember, GeoJSON doesn’t care what data you associate with the location information.
  • FeatureCollection: Basically just a list of feature objects.

So typically one GeoJSON file (or dataset) will consist of a FeatureCollection containing a list of your data.

Let’s take a look at a simple example.

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [ -90.0715, 29.9510 ]
      },
      "properties": {
        "name": "Fred",
   		"gender": "Male"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [ -92.7298, 30.7373 ]
      },
      "properties": {
        "name": "Martha",
   		"gender": "Female"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [ -91.1473, 30.4711 ]
      },
      "properties": {
        "name": "Zelda",
	    "gender": "Female"
      }
    }
  ]
}

At the top level you can see that I’m defining a FeatureCollection, or list of data. I then define my features, which is an array of Feature objects. Each Feature has a geometry object and a properties object. The geometry object will either be a Point, LineString, Polygon, MultiPoint, MultiLineString, or MultiPolygon. Each type should be pretty self-explanatory but certainly leave a comment if any aren’t clear. Inside properties you can see I’ve specified both a name and gender value for my cats. I can specify any data here at all, but as you can imagine, putting some thought into it and being consistent will go a long way to making your data more useful.

Working with GeoJSON

So given that you want to work with this type of file, how can you work with and display your data? The good news is that it’s just JSON. If you’re using JavaScript, the “effort” involved is a grand total of one line of code:

let myData = JSON.parse(dataILoadedViaAjaxOrSomeSuch);

At that point you’ve got your structured data and can then iterate over the features and do… well whatever you want with them. Consider this example where I use Vue to load in the JSON above and render it as an unordered list. First the HTML:

<div id="app" v-cloak>
  <ul>
    <li v-for="cat in cats">
      Cat {{ cat.name }} is {{ cat.gender }}
      and is located at {{ cat.pos.lat }}, {{ cat.pos.lon }}
    </li>
  </ul>
</div>

Then the JavaScript:

Vue.config.productionTip = false;
Vue.config.devtools = false;

const DATA = 'https://api.jsonbin.io/b/5d6ed60b2d1fb96463c30e63';

const app = new Vue({
  el:'#app',
  data:{
    cats:[]
  },
  async created() {
    let response = await fetch(DATA);
    let geodata = await response.json();
    this.cats = geodata.features.map(c => {
      return {
        name:c.properties.name,
        gender:c.properties.gender,
        pos: {
          lat:c.geometry.coordinates[0],
          lon:c.geometry.coordinates[1],
        }
      }
    });
  }
})

Note I do a bit of mapping on the GeoJSON to make it simpler to use in the HTML. There’s no reason the layout need know of the GeoJSON format. You can see the result below (and feel free to play with the code):

See the Pen geojson1 by Raymond Camden (@cfjedimaster) on CodePen.

How about rendering on a map? HERE’s Map Image API makes it easy to display points of interest on a map. I changed my HTML to render an image:

<div id="app" v-cloak>
  <h2>My Cats</h2>
  <img :src="src" v-if="poiList">
</div>

And my JavaScript now generates an image URL based on the Map Image API:

Vue.config.productionTip = false;
Vue.config.devtools = false;

const DATA = 'https://api.jsonbin.io/b/5d6ed60b2d1fb96463c30e63';
const APP_ID = 'your app id here';
const APP_CODE = 'your app code here';

const app = new Vue({
  el:'#app',
  data:{
    poiList:''
  },
  async created() {
    let response = await fetch(DATA);
    let geodata = await response.json();
    this.poiList = geodata.features.reduce((acc, curr) => {
      if(acc !== '') acc += ',';
      return acc += curr.geometry.coordinates[1] + ',' + curr.geometry.coordinates[0]
    },'');
  },
  computed:{
    src() {
      return `https://image.maps.api.here.com/mia/1.6/mapview?app_id=${APP_ID}&app_code=${APP_CODE}&poi=${this.poiList}&w=400&h=300&z=8`;
    }
  
  
  }
})

Feel free to play around with this version here:

See the Pen geojson2 by Raymond Camden (@cfjedimaster) on CodePen.

Testing GeoJSON

So hey, you absolutely love GeoJSON and want to give it a spin in your own applications? Of course you do! Here’s two tools to help make working with GeoJSON easier.

First, if you’re a Visual Studio Code user (and let’s be honest, most of you are), you can find an excellent extension called VSCode Map Preview. As you can guess, this extension provides a map view of your GeoJSON data. Given the cat data I shared earlier, I can hit F1, run Map Preview, and get the following output:

map

This is a handy little tool, but note that it doesn’t currently support updating when you edit your text. You’ll have to close and re-open the preview to see changes. (This is a known issue.)

Another option is the GeoJSON Viewer created by the HERE XYZ team. It has a built in editor and viewer. What’s cool is that the editor provides validation on your data. As you can see here, I’m clearly not providing the right information and I’ve got real time feedback about my issues.

editor1
editor2

The Viewer also lets you import GeoJSON data via URL or files. I took data from the National Park’s System GeoJSON file and imported it into the viewer:

map2
As you can see, it does a pretty impressive job of rendering a lot of data!

What Else?

Obviously as a simple, easily to parse spec, there’s quite a bit you can do with GeoJSON. Industry adoption will impact how successful this spec is, but if you are already offering your data via an API, there’s no reason not to support this format. Give it a try and if you’ve got an example of your own use of GeoJSON, leave me a comment below!