GeoJSON

GeoJSON is a popular format for encoding geographic data. Its specification describes nine different types a message may take (seven “geometry” types, plus two “feature” types). Here we provide one way of implementing that specification using msgspec to handle the parsing and validation.

The loads and dumps methods defined below work similar to the standard library’s json.loads/json.dumps, but:

  • Will result in high-level msgspec.Struct objects representing GeoJSON types

  • Will error nicely if a field is missing or the wrong type

  • Will fill in default values for optional fields

  • Decodes and encodes significantly faster than the json module (as well as most other json implementations in Python).

This example makes use msgspec.Struct types to define the different GeoJSON types, and Tagged Unions to differentiate between them. See the relevant docs for more information.

The full example source can be found here.

from __future__ import annotations

import msgspec

Position = tuple[float, float]


# Define the 7 standard Geometry types.
# All types set `tag=True`, meaning that they'll make use of a `type` field to
# disambiguate between types when decoding.
class Point(msgspec.Struct, tag=True):
    coordinates: Position


class MultiPoint(msgspec.Struct, tag=True):
    coordinates: list[Position]


class LineString(msgspec.Struct, tag=True):
    coordinates: list[Position]


class MultiLineString(msgspec.Struct, tag=True):
    coordinates: list[list[Position]]


class Polygon(msgspec.Struct, tag=True):
    coordinates: list[list[Position]]


class MultiPolygon(msgspec.Struct, tag=True):
    coordinates: list[list[list[Position]]]


class GeometryCollection(msgspec.Struct, tag=True):
    geometries: list[Geometry]


Geometry = (
    Point
    | MultiPoint
    | LineString
    | MultiLineString
    | Polygon
    | MultiPolygon
    | GeometryCollection
)


# Define the two Feature types
class Feature(msgspec.Struct, tag=True):
    geometry: Geometry | None = None
    properties: dict | None = None
    id: str | int | None = None


class FeatureCollection(msgspec.Struct, tag=True):
    features: list[Feature]


# A union of all 9 GeoJSON types
GeoJSON = Geometry | Feature