Converting Python Dictionaries to GeoJSON: A Guide to 5 Effective Methods

πŸ’‘ Problem Formulation: GeoJSON is a widely-used format for encoding a variety of geographic data structures. In cases where geographic data is initially stored in a Python dictionary, it’s often necessary to convert it to GeoJSON for use with mapping tools and web applications. This article will detail how one can turn a Python dict that follows GeoJSON structure into a properly formatted GeoJSON string or file. For example, converting { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [125.6, 10.1] }, "properties": { "name": "Dinagat Islands" }}]} into a GeoJSON format.

Method 1: Using json.dump()

This method entails the use of Python’s built-in JSON library to serialize a Python dict object into a JSON formatted string and then directly write it into a file. The file can be explicitly written as a .geojson which can be used by various applications that support GeoJSON.

Here’s an example:

import json

data = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [125.6, 10.1]
            },
            "properties": {
                "name": "Dinagat Islands"
            }
        }
    ]
}

with open('data.geojson', 'w') as f:
    json.dump(data, f, indent=4)

Output: A file named data.geojson will be created with properly formatted GeoJSON content.

This code snippet demonstrates serializing a Python dictionary with geographic data to a GeoJSON formatted file using json.dump(). The method is straightforward and efficient for writing to files without the need for additional libraries.

Method 2: Using json.dumps()

Similar to the previous method, Python’s built-in JSON library can be used. However, by using json.dumps(), the dict is converted into a JSON formatted string, which can then be manipulated or stored according to the user’s needs before eventually being saved as a GeoJSON file.

Here’s an example:

import json

dict_data = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-105.01621, 39.57422]
            },
            "properties": {
                "name": "Denver"
            }
        }
    ]
}

geojson_str = json.dumps(dict_data, indent=4)
print(geojson_str)

Output:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-105.01621, 39.57422]
            },
            "properties": {
                "name": "Denver"
            }
        }
    ]
}

The above code snippet converts the Python dictionary containing geographic data into a pretty-printed GeoJSON string using json.dumps(). This is useful when you need the GeoJSON data as a string to pass to other functions or APIs instead of writing it to a file.

Method 3: Using a Custom Function

If standardized GeoJSON structures need to be generated from non-standard Python dicts, a custom function can be written to map the dict to valid GeoJSON format. This method can enforce GeoJSON specification and handle exceptions as necessary.

Here’s an example:

def dict_to_geojson(data_dict):
    # Assume data_dict is well-formed and resembles GeoJSON 'FeatureCollection'
    return {
        "type": "FeatureCollection",
        "features": data_dict.get('features', [])
    }

raw_data = {
    "features": [
        {
            "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"
            }
        }
    ]
}

geojson_data = dict_to_geojson(raw_data)
print(geojson_data)

Output:

{
    "type": "FeatureCollection",
    "features": [
        {
            "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"
            }
        }
    ]
}

In this snippet, we see a custom function dict_to_geojson() which processes the incoming dict and structures it according to GeoJSON ‘FeatureCollection’ type. This is particularly helpful when dealing with non-standard dict structures that need conforming to the GeoJSON specification.

Method 4: Using the geojson Library

For more advanced manipulation of GeoJSON data or simply to adhere better to the GeoJSON specification, the geojson package can be utilized. This library provides utilities to generate GeoJSON from Python objects directly.

Here’s an example:

import geojson

point = geojson.Point((-115.81, 37.24))
feature = geojson.Feature(geometry=point, properties={"name": "Area 51"})
feature_collection = geojson.FeatureCollection([feature])

print(geojson.dumps(feature_collection, indent=4))

Output:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-115.81, 37.24]
            },
            "properties": {
                "name": "Area 51"
            }
        }
    ]
}

The geojson library is used here to create GeoJSON objects directly. The Point, Feature, and FeatureCollection are classes provided by the library which helps to maintain the correct structure and ensures adherence to the specification.

Bonus One-Liner Method 5: Using dict comprehensions with json.dumps()

This method is suitable for cases where a dictionary directly translates to a GeoJSON FeatureCollection with minimal transformation. Dict comprehensions can quickly transform lists or other structures within the Python dict before using json.dumps() to convert to GeoJSON string format.

Here’s an example:

import json

data = {"locations": [{"lat": 42.0, "lon": -81.0, "name": "Location A"}, {"lat": 43.2, "lon": -82.1, "name": "Location B"}]}
geojson = json.dumps({"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [d["lon"], d["lat"]]}, "properties": {"name": d["name"]}} for d in data["locations"]]}, indent=4)

print(geojson)

Output:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-81.0, 42.0]
            },
            "properties": {
                "name": "Location A"
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [-82.1, 43.2]
            },
            "properties": {
                "name": "Location B"
            }
        }
    ]
}

This one-liner uses a list comprehension within the json.dumps() function to iterate through a list of locations in the dictionary and creates GeoJSON feature objects dynamically. This is a quick and concise way to generate GeoJSON from Python dicts when the data requires minimal processing.

Summary/Discussion

  • Method 1: Using json.dump(): Best for writing GeoJSON data directly to files. Straightforward, but less flexible when content needs to be manipulated before saving.
  • Method 2: Using json.dumps(): Best for converting dict to GeoJSON string. Provides more control for intermediate processing. The result must be explicitly written to a file if needed.
  • Method 3: Using a Custom Function: Ideal for non-standard dictionaries or when specific validation is required. Requires more code and maintenance.
  • Method 4: Using the geojson Library: Offers a more Pythonic approach and better compliance with the GeoJSON specification. Requires an external library.
  • Method 5: Using dict comprehensions with json.dumps(): A concise one-liner for simple transformations of dict data to GeoJSON. Limited by the complexity of the transformation that can be handled.