Creating a GeoJSON FeatureCollection Type for GraphQL

Using a custom Scalar type to return feature geometry

Bryan Grill

--

I recently needed to return a GeoJSON FeatureCollection as a type for a GraphQL Server. I ran into a minor hurdle when trying to return the coordinates as a lon/lat array:

"coordinates": [0, 0]

There is not a standard GraphQL Type to handle this data structure. So you need to create a custom Scalar type.

If you want to save yourself the headache, you can add the graphql-geojson package for JS or the graphql-geojson-go package for Go. If you’d like to do it yourself, here is a brief summary of what I put together.

GeoJSON Schema

Here is a simple GeoJSON FeatureCollection schema that we’ll model for our GraphQL type, aFeatureCollection with an array of Features with Point geometry:

{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-75, 40]
},
"properties": {
"id": 1
}
}
]
}

If you want to read more about GeoJSON, here is a great blog post and here is the official spec.

GraphQL Schema

We need to build our schema to follow the structure of the above GeoJSON. This example uses GraphQL.js and graphql-tools, but could be applied to any GraphQL spec. If you are not familiar with graphql-tools, here are the docs on generating a schema.

Here is our schema formatted for graphql-tools:

This schema is for a mock transit feed of bus locations. Stepping through our schema:

  • From the Query we build out the GraphQL types that will map to a GeoJSON FeatureCollection.
  • The FeatureCollection type contains an array of the PointObject type, these are the features.
  • Each PointObject contains a PointGeometry and PointProps for the geometry and properties respectively.
  • The PointGeometry type returns the point coordinates via our custom Coordinates scalar.
  • The PointProps type will return attributes specific to the feature.

Custom Scalar

Before we construct our resolver, we need to create our custom scalar to handle the coordinates array. Here is what it looks like:

What this is doing is returning whatever value is passed into the type. You will see below, we pass in an array of [lon, lat] and that is exactly what is returned. Thanks to the graphql-geojson repo and Apollo docs for the code.

GraphQL Resolver

Now we can construct our resolver in the graphql-tools format and we’ll be all set. Here are the docs on writing resolvers with graphql-tools.

Here is our full resolver:

Each object in the resolver maps to a type in our schema. The methods within each object resolve to their corresponding fields as described in the schema above.

GraphQL Request

To make a request that would return a properly constructed GeoJSON Feature Collection, you would submit something like this:

{
transit_feed {
type
features {
type
geometry {
type
coordinates
}
properties {
id
}
}
}
}

I hope you found this brief example helpful. If you’d like to see it in action, here it is as an Apollo Launchpad.

--

--

Bryan Grill

Software Developer — frontend, backend, devops. Mostly React these days.