Reading the geographic information in GeoJSON

1 Transferring geographic information

In the D3 world, we can share geographic data mainly in two formats: TopoJSON and GeoJSON; they both follow the JSON standard.

As mentioned, GeoJSON is a standard used to keep geographic information. The info blocks it may contain include: points (thus, addresses and locations), line segments (thus, streets, highways, and limits), polygons (thus, countries, provinces, and land segments), as well as combinations of such blocks. It is worth noticing that these information blocks are not required to represent physical entities. For instance, usually, the states inside a country do not have a physical barrier between them; this is, no obstacle in the terrain would prevent you to go from one state to the other; still, there is no inconvenient in creating a GeoJSON object to represent a state.

On the other hand, TopoJSON is a sub-set of GeoJSON; i.e. the former is based on the latter. Unlike GeoJSON, D3 cannot directly work with TopoJSON; therefore, we need to “translate” it to the GeoJSON standard before we can use it. Then, you may be wondering: what is the use of TopoJSON given that, at any rate, we are unable to use it directly for D3? Well, because of the way they’re structured, the TopoJSON files tend to be smaller and they are capable of holding more data than their GeoJSON counterparts. This can be an enormous advantage, for example, if you have a server that provides clients with geographical data; since your aim is to maintain a responsive server, it’d play in your favor to serve small files and let the client give any further processing required. Moreover, the TopoJSON standard was designed to consider the ground topology, i.e. the terrain’s altitude; this aspect is not natively addressed in the GeoJSON standard.

By the way, if you wish to know the full GeoJSON specification, you can visit geojson.org.

2 GeoJSON structure

2.1 What does it take to be a GeoJSON object?

2.1.1 The types of GeoJSON objects

There are three main “species” of GeoJSON objects:

  • Geometry: It is a region of space, in its broader sense. These regions should be embedded in a coordinate space; this is, a space divided in coordinates; for example, longitude and latitude. Any region we are able to locate in a coordinate space can be described through a Geometry object
  • Feature: It represents a spatially bounded entity. This means that, besides being able to contain spatial information, it also contains information that describes what that region of space signifies. An example may be helpful; consider this: in order to represent a country, we need not only the global position of that country; some other relevant information to identify it could be: its complete name, a short name, what continent it is in, what language is spoken in it, etc. Besides countries, some other spatially bounded entities can be: states, counties, blocks, etc.
  • FeatureCollection: It is simply a collection of Feature objects.

In turn, there exist seven types of Geometry objects; thus, there can be nine GeoJSON object types

2.1.2 The type property

All GeoJSON objects must have a property called type; in it, you must indicate any of the nine possible GeoJSON object types: “Point”, “LineString”, “Polygon”, “MultiPoint”, “MultiLineString”, “MultiPolygon”, “GeometryCollection”, “Feature” or “FeatureCollection”.

2.1.3 Arbitrary properties in the GeoJSON objects

It is also valid for the GeoJSON objects to have any other arbitrary property; even if it is not specified by the GeoJSON standard. The objects linked to such properties are called foreign-objects and they are never considered GeoJSON objects, no matter the name of their properties. You may be thinking: what is the use of adding this kind of properties? after all, what we want is to transfer cartographic information, don’t we? You see, these kinds of properties may come in handy for times when you wish to indicate specific information about the region being represented by the GeoJSON object; for instance, you could create a property for the name of a country, another one for the language spoken in it, one more to signal the population count, etc. Remember, a geo-referenced visualization is only useful if it assists you to tell a story about your data; the arbitrary properties may be a good place to store information that helps you tell that story.

2.2 The Geometry object

2.2.1 Background

As you may recall, a Geometry object represents points, curves, and surfaces in a coordinate space.

2.2.1.1 The coordinates property

With the exception of the GeometryCollection object, all Geometry objects must have a property called coordinates; in it, we can indicate the information related to the position of the object.

2.2.1.2 Position and base-position

The position is the fundamental construction of a Geometry object.

In its simplest form, a position is an array of decimal numbers; this is called a base-position. The first two numbers of the base-position are longitude and latitude, in that order. Optionally, there may be a third parameter that represents altitude; however, not all GeoJSON parsers are capable of interpreting this datum; so, no guarantees there.

An interesting point to note is the fact that the position information is built differently across the Geometry objects; for instance, in the case of the Point object, we can use a single base-position; on the other hand, an array of base-positions would be necessary for the LineString and MultiPoint objects. Next, we will explore this in detail.

2.2.2 Types of Geometry objects

There are seven types of Geometry objects; hence, the type property must have, according to the case, one the these values: “Point”, “LineString”, “Polygon”, “MultiPoint”, “MultiLineString”, “MultiPolygon” o “GeometryCollection”.

2.2.2.1 Point

  • It represents a single point in a map.
  • Its coordinates property is a single base-position; for example: [-109.952621, 22.873550].

2.2.2.2 MultiPoint

  • It is a group of points in a map.
  • The coordinates property is an array of base-positions; for example: [[-109.952621, 22.873550], [-117.152752, 32.511857], [-106.389995, 31.729324]]

2.2.2.3 LineString

  • It represents a line in the map. To form this line, we need at least two points, which precisely stand for the beginning and the end of the line.
  • The coordinates property is an array of two or more base-positions; just as in the case of the MultiPoint object.
  • The difference between this and the MultiPoint object is that, in the latter, the set of points do not form a line; rather, they remain as a group of independent points.

2.2.2.4 MultiLineString

In this case, the coordinates property is an array of positions as those indicated in the LineString object; i.e. an array of arrays of arrays (three levels); for instance:

[
    [[-101.830050, 29.821814], [-97.103269, 25.889812], [-97.366612, 21.168504]]
    ,[[-86.818797, 21.067803], [-92.307206, 14.541265], [-94.745877, 16.296351]]
    ,[[-105.705476, 20.346444], [-114.719173, 31.663829], [-109.396981, 23.349035]]
]

2.2.2.5 Polygon

In order to better comprehend the Polygon object, we need to introduce a new concept: linear-ring.

  • A linear-ring is not by itself a GeoJSON object; nevertheless, it is an important notion if you want to fully understand the Polygon object.
  • You can think of the linear-ring as a kind of closed LineString.
  • The linear-ring is an array with at least four base-positions; where the first and the last base-positions are equivalent and must always have identical values.
  • As an example of a linear-ring, we have this array: [[-105.705476, 20.346444], [-114.719173, 31.663829], [-109.396981, 23.349035], [-105.705476, 20.346444]].
  • A linear-ring may represent the limits of a surface, in which case we would be talking about an exterior ring; it is only possible to have a single exterior ring in the Polygon object. It is also valid for a linear-ring to represent a hole on the surface; in this case it is called an interior ring; we can have more than one interior ring.

Once clarified the linear-ring concept, it is much simpler to define the Polygon object:

  • The coordinates property of the Polygon object must be an array of linear-rings.
  • For Polygon objects with more than one linear-ring, the first one must represent an exterior ring, and the rest of them, if any, represent interior rings.
  • As an example of a position, we have the following:
[
    [[1, 7], [2, 2], [8, 2], [9, 8], [4, 9], [1, 7]]
    ,[[2, 7], [3, 8], [3, 6], [2, 7]]
    ,[[3, 3], [5, 4], [6, 3], [3, 3]]
    ,[[6, 7], [8, 7], [6, 5], [6, 7]]
]

2.2.2.6 MultiPolygon

For this object, the coordinates property is an array of coordinates as those indicated in the Polygon object; for instance:

[
 [
  [[0, 6], [1, 1], [7, 1], [8, 7], [3, 8], [0, 6]]
  ,[[1, 6], [2, 7], [2, 5], [1, 6]]
  ,[[2, 2], [4, 3], [5, 2], [2, 2]]
  ,[[5, 6], [7, 6], [5, 4], [5, 6]]
 ]
 ,[
  [[1, 7], [2, 2], [8, 2], [9, 8], [4, 9], [1, 7]]
  ,[[2, 7], [3, 8], [3, 6], [2, 7]]
  ,[[3, 3], [5, 4], [6, 3], [3, 3]]
  ,[[6, 7], [8, 7], [6, 5], [6, 7]]
 ]
 ,[
  [[2, 8], [3, 3], [9, 3], [10, 9], [5, 10], [2, 8]]
  ,[[3, 8], [4, 9], [4, 7], [3, 8]]
  ,[[4, 4], [6, 5], [7, 4], [4, 4]]
  ,[[7, 8], [9, 8], [7, 6], [7, 8]]
 ]
]

2.2.2.7 GeometryCollection

  • This object has a property called geometries; said property is an array of Geometry objects. It is also valid for this array to be empty.
  • This is the only Geometry object that can be composed of other Geometry objects.
  • This object doesn’t have a coordinates property.
  • It is not desirable for a GeometryCollection to contain another GeometryCollection; while it is possible.
  • If you think about it for a second, using this object only makes sense if the child objects that compose it belong to different kinds; otherwise, according to the case, it is really more convenient to use a MultiPoint, MultiLineString or MultiPolygon object.

2.3 The Feature object

It is a GeoJSON object that represents any spatially bounded entity. The type property of these objects must have as value “Feature”.

The Feature object has three properties inherent to it:

  • geometry: Its value can only be a Geometry object or null.
  • properties: In it, you can indicate any information you want; it is even possible to link it to a JSON object or null.
  • id: The value for this property may be a number or a text string. It is only used in times when the information described by the Feature object, has a commonly used identification. For example, the numeric code indicated by ISO 3166 for Argentina is 032. The id property could work as a good place to input this information.

As you may have noticed, the Feature object is pretty useful; on the one hand, it is able to storage cartographic information in its geometry property; on the other and, its properties property works as an excellent point to indicate any other info data set about the spatial region represented by the Feature object.

2.4 The FeatureCollection object

  • The type property of this object must have the value “FeatureCollection”.
  • The other inherent property of this object, is features, whose value is an array of Feature objects.

3 Once more, please, what object has what property?

Do you feel overwhelmed with so many different properties in so many different objects? Fear not! I have prepared a table where you will be able to find exactly what property must be included in every GeoJSON object. Just remember, all GeoJSON objects may additionally have arbitrary properties

Object type Properties
type coordinates geometries geometry properties id features
Geometry Point X X
LineString X X
Polygon X X
MultiPoint X X
MultiLineString X X
MultiPolygon X X
GeometryCollection X X
Feature X X X X
FeatureCollection X X

4 Example of a GeoJSON obect

Are you wondering how a real-life GeoJSON object actually looks like? The following example, taken from tools.ietf.org , will give you a clear idea. In this case, all the information is wrapped in a FeatureCollection object.

At this point, you should be able to read this object. Go ahead, don’t be shy, try it!

    {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [102.0, 0.5]
                },
                "properties": {
                    "prop0": "value0"
                }
            }, 
            {
                "type": "Feature",
                "geometry": {
                    "type": "LineString",
                    "coordinates": [
                        [102.0, 0.0],
                        [103.0, 1.0],
                        [104.0, 0.0],
                        [105.0, 1.0]
                    ]
                },
                "properties": {
                    "prop0": "value0",
                    "prop1": 0.0
                }
            }, 
            {
                "type": "Feature",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [
                        [
                            [100.0, 0.0],
                            [101.0, 0.0],
                            [101.0, 1.0],
                            [100.0, 1.0],
                            [100.0, 0.0]
                        ]
                    ]
                },
                "properties": {
                    "prop0": "value0",
                    "prop1": {
                        "this": "that"
                    }
                }
            }
        ]
    }

5 Wrapping up

You may have realized that, in fact, there are many possibilities to structure the geographic information. It is possible to have two perfectly valid GeoJSON objects, structured in different fashions but capable of transmitting the same information. The key point is for you to be able to identify where the information you need for your particular application is.

Finally, unless you are creating new cartographic information, it is highly unlikely that you ever need to manually build your own GeoJSON objects. Usually, you will use files that already exist or you could use tools like mapshaper.org to transform from a different format to the GeoJSON standard. Being so, why to even bother in knowing this standard? You see, the ability to understand how these objects work will be instrumental in your capability to recognize and find all the information that is usually wrapped inside the GeoJSON objects. This way, you can take the most out of them for your projects!