GeoJSON codec for Go structs
The library implements a type safe codec for GeoJSON.
GeoJSON is a popular format for encoding a variety of geographic data structures. It defines a standard way to express points, curves, and surfaces in coordinate space together with an application specific metadata about it.
{
"type": "Feature",
"id": "[wikipedia:Helsinki]",
"geometry": {
"type": "Point",
"coordinates": [24.9384, 60.1699]
},
"properties": {
"name": "Helsinki"
}
}
Unfortunately, efficient and type-safe implementation of GeoJSON codec can be challenging:
(i) Pure structs are verbose. The properties
is an application specific and it's type is controlled outside of the codec library. Usage of duck type (interface{}
) is a common trait used by other GeoJSON Golang libraries. As the results, developers are misses an ability to caught errors at compile time, any mistake becomes visible at run time as a panic. interface{} says nothing..
(ii) Implementing GeoJSON types using generics is requires overly complex type definitions. It can lead to complex type hierarchies, especially in nested GeoJSON structures like FeatureCollection. It suffers from usability for consumers. Specifying types for properties at every level (e.g., Feature or FeatureCollection) adds boilerplate and increases the learning curve.
The library allows developers to use Golang pure struct to define domain models using a type safe approach of encoding/decoding these models to GeoJSON and back. The library uses type tagging technique to annotate any structure as GeoJSON feature:
type City struct {
geojson.Feature
Name string `json:"name,omitempty"`
}
The latest version of the library is available at main
branch of this repository. All development, including new features and bug fixes, take place on the main
branch using forking and pull requests as described in contribution guidelines. The stable version is available via Golang modules.
The following code snippet demonstrates a typical usage scenario.
import "github.com/fogfish/geojson"
//
// declare any domain type and annotate as a geojson.Feature
type City struct {
geojson.Feature
Name string `json:"name,omitempty"`
}
//
// Each GeoJSON type declares codes using helper functions.
func (x City) MarshalJSON() ([]byte, error) {
type tStruct City
return x.Feature.EncodeGeoJSON(tStruct(x))
}
func (x *City) UnmarshalJSON(b []byte) error {
type tStruct *City
return x.Feature.DecodeGeoJSON(b, tStruct(x))
}
//
// Create new instance of the type
city := City{
Feature: geojson.NewPoint(
"[wikipedia:Helsinki]",
geojson.Coord{24.9384, 60.1699},
),
Name: "Helsinki",
}
//
// Use type checks to validate the type of the Geometry
city.Feature.Geometry.Coords.(*geojson.Point)
The library supports FeatureCollection
object via Golang generic.
seq := geojson.Collection[City]{
Features: []City{city},
}
The library is MIT licensed and accepts contributions via GitHub pull requests:
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
The build and testing process requires Go version 1.16 or later.
build and test library.
git clone https://github.com/fogfish/geojson
cd geojson
go test
The commit message helps us to write a good release note, speed-up review process. The message should address two question what changed and why. The project follows the template defined by chapter Contributing to a Project of Git book.
If you experience any issues with the library, please let us know via GitHub issues. We appreciate detailed and accurate reports that help us to identity and replicate the issue.