geojson is a Go package implementing the RFC 7946 standard. It provides full support for GeoJSON objects, including Features, FeatureCollections, and Geometries, offering comprehensive functionality for serializing and deserializing GeoJSON data.
- Strict adherence to the RFC 7946 GeoJSON standard.
- Support for GeoJSON object types:
- Feature
- with ID and Properties
- FeatureCollection
- Geometries
- Supported geometries:
Point
,LineString
,Polygon
,MultiPoint
,MultiLineString
,MultiPolygon
, andGeometryCollection
.
- Supported geometries:
- Feature
- Robust validation of object types and coordinates.
- Bounding box generation.
- Polygon and MultiPolygon linear rings are automatically oriented to follow the right-hand rule: outer rings are counterclockwise, holes are clockwise.
- All wrappers, features and geometries support JSON marshalling and unmarshalling
go get github.com/aoliveti/geojson
The geojson.Object
is a generic representation of a GeoJSON object, providing the tools to parse, inspect, and work with GeoJSON features and metadata. This structure is useful for handling GeoJSON data programmatically by offering methods to determine the type of GeoJSON object and interact with its contents.
- Methods:
Type()
- Returns the GeoJSON type (Feature
orFeatureCollection
).IsFeature()
- Checks if the object is a Feature.IsFeatureCollection()
- Checks if the object is a FeatureCollection.Feature()
- Retrieves the Feature object (error if not a feature).FeatureCollection()
- Retrieves the FeatureCollection (error if not a collection).MarshalJSON()
/UnmarshalJSON()
- Converts the object to/from JSON.
The possible types include:
TypeEmptyObject
: Represents an invalid or uninitialized GeoJSON object.TypeFeature
: Indicates the object is a single GeoJSON Feature.TypeFeatureCollection
: Indicates the object is a GeoJSON FeatureCollection.
Here is a quick overview of how to work with geojson.Object
and its methods:
data := `{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [102.0, 0.5]
},
"properties": {
"name": "Sample Point"
}
}`
var obj geojson.Object
if err := obj.UnmarshalJSON([]byte(data)); err != nil {
...
}
if !obj.IsFeature() {
...
}
feature, _ := obj.Feature()
fmt.Println(feature)
}
The geojson.Feature
represents a single GeoJSON Feature. It consists in a spatial geometry, properties, and optionally an ID. The Feature
object also supports operations such as calculating bounding boxes and extracting vertices.
-
Attributes:
Geometry
: Specifies the spatial information of the feature (point, line, polygon, etc.).Properties
: A map containing additional metadata about the feature.ID
: An optional identifier for the feature.SerializeBBox
: A flag determining whether to include a bounding box in serialized output.
-
Feature Builder: Use the
FeatureBuilder
to programmatically build aFeature
with the following methods:SetGeometry(geometry Geometry)
SetProperties(properties Properties)
SetID(id ID)
Build()
geometry := geojson.MustPoint([]float64{102.0, 0.5})
properties := geojson.Properties{"name": "Sample Point"}
builder := geojson.NewFeatureBuilder()
feature := builder.SetGeometry(geometry).
SetProperties(properties).
Build()
data, err := json.Marshal(&feature)
if err != nil {
...
}
fmt.Println(string(data))
The geojson.FeatureCollection
represents a GeoJSON object that contains a collection of Feature
objects.
-
Attributes:
Features
: A list ofFeature
objects in the collection.SerializeBBox
: A flag determining whether to include a bounding box in serialized output.
-
Constructor Methods:
NewFeatureCollection()
: Creates an emptyFeatureCollection
.NewFeatureCollectionFromFeatures(features []Feature)
: Initializes aFeatureCollection
with the given slice of features.
features := []geojson.Feature{feature1, feature2, feature3}
collection := geojson.NewFeatureCollectionFromFeatures(features)
The Properties
type manages metadata as key-value pairs for GeoJSON features.
- Add/Update: Use
Set("key", value)
to add or update properties. - Retrieve: Use
Get("key")
or typed methods (GetString
,GetInt
, etc.) for type-safe access.
Example:
properties := geojson.Properties{}
properties.Set("name", "Foo")
name, _ := properties.GetString("name")
Typed methods return errors for missing keys or type mismatches, such as ErrPropertyNotFound
.
The geojson.GeometryObject
serves as a generic wrapper for GeoJSON geometries. Its main purpose is to handle GeoJSON geometry data during the unmarshalling process, allowing for flexible deserialization and easy identification of the actual geometry type. Additionally, it provides methods to safely access specific geometry types and convert the wrapped geometry into the desired structure.
-
Generic Geometry Wrapping:
TheGeometryObject
wraps any GeoJSON-compatible geometry, including:- Point
- LineString
- MultiPoint
- MultiLineString
- Polygon
- MultiPolygon
- GeometryCollection
-
Geometry Identification:
The type of the contained geometry can be identified using theType()
method, which returns aGeometryType
. -
Safe Type Conversion:
TheGeometryObject
provides methods to check whether the contained geometry matches a specific type and to convert the contained geometry into a strongly typed object (e.g.,Point
,LineString
, etc.). -
Marshalling/Unmarshalling Support:
TheGeometryObject
handles serialization to and deserialization from GeoJSON formatted data, ensuring compatibility with the GeoJSON format.
- Geometry Type and State Methods:
-
func (g *GeometryObject) Type() GeometryType
Returns the type of the contained geometry (e.g.,Point
,Polygon
, etc.). -
func (g *GeometryObject) IsEmpty() bool
Checks if theGeometryObject
is empty or not defined. -
Specific Type Check Methods:
IsPoint()
,IsLineString()
,IsMultiPoint()
,IsMultiLineString()
,IsPolygon()
,IsMultiPolygon()
,IsGeometryCollection()
- Type Conversion Methods:
Converts the contained geometry into a strongly typed object and returns an error if the type does not match:
ToPoint() (*Point, error)
ToLineString() (*LineString, error)
ToMultiPoint() (*MultiPoint, error)
ToMultiLineString() (*MultiLineString, error)
ToPolygon() (*Polygon, error)
ToMultiPolygon() (*MultiPolygon, error)
ToGeometryCollection() (*GeometryCollection, error)
- Marshalling and Unmarshalling:
-
func (g *GeometryObject) MarshalJSON() ([]byte, error)
Serializes theGeometryObject
into GeoJSON format. Returns an error if the geometry is not defined. -
func (g *GeometryObject) UnmarshalJSON(data []byte) error
Deserializes GeoJSON data into theGeometryObject
. Automatically detects and handles the actual geometry type (e.g., Point, Polygon, etc.).
- Wrap existing Geometry:
static func FromGeometry(g Geometry) GeometryObject
Creates a newGeometryObject
from an existingGeometry
.
// Unmarshal GeoJSON data (e.g., for a Point)
geoJSONData := []byte(`{
"type": "Point",
"coordinates": [100.0, 0.0]
}`)
err := gObj.UnmarshalJSON(geoJSONData)
if err != nil {
...
}
// Identify Geometry Type
if gObj.IsPoint() {
point, err := gObj.ToPoint()
if err != nil {
...
}
// Use point
}
// Use a switch to check and handle the geometry type
switch gObj.Type() {
case geojson.TypePoint:
point, err := gObj.ToPoint()
if err != nil {
...
}
case geojson.TypeLineString:
lineString, err := gObj.ToLineString()
if err != nil {
...
}
...
}
The geojson.Coordinates
type represents a GeoJSON coordinate array (WGS84), containing longitude, latitude, and optionally altitude.
- Longitude:
-180 <= longitude <= 180
- Latitude:
-90 <= latitude <= 90
- Coordinates must have either 2 elements (
[longitude, latitude]
) or 3 elements ([longitude, latitude, altitude]
). Longitude()
: Returns the longitude value of the coordinates.Latitude()
: Returns the latitude value of the coordinates.HasAltitude()
: Checks if the coordinates include an altitude.Altitude()
: Returns the altitude value (if present).NewCoordinates([]float64) (*Coordinates, error)
: Creates a newCoordinates
object from a float64 array. Returns an error for invalid input.MustCoordinates([]float64) *Coordinates
: Creates aCoordinates
object and panics on error.
coordinates, err := geojson.NewCoordinates([]float64{12.4924, 41.8902, 45})
if err != nil {
...
}
fmt.Println("longitude:", coordinates.Longitude())
fmt.Println("latitude:", coordinates.Latitude())
if coordinates.HasAltitude() {
fmt.Println("altitude:", coordinates.Altitude())
}
The geojson.Vertices
type is a collection of Coordinates
used to define geometric shapes (e.g., a line or polygon).
Allows grouping multiple Coordinates
into a structured, ordered collection.
The geojson.Segments
type represents a collection of line segments, constructed from groups of Vertices
. These segments are commonly used to define continuous or discrete line geometries, such as MultilineStrings.
The geojson.LinearRing
type represents a closed linear ring, a sequence of connected vertices forming a continuous loop. Linear rings are commonly used in GeoJSON Polygons and MultiPolygons, defining their outer and inner boundaries (holes). This type includes methods for validation, orientation, and basic geometric calculations.
- Validation:
- Ensures the linear ring has at least the required minimum points (
4
coordinates, including the closing point). - Ensures the first and last coordinates are identical (i.e., the ring is closed).
- Orientation:
- Determines whether the linear ring is ordered clockwise or counterclockwise based on the signed area of its vertices.
- Provides functionality to adjust the orientation to meet specific requirements (e.g., outer rings counterclockwise and inner rings clockwise).
- Geometry Calculations:
- Computes the absolute area of the linear ring.
All geometries in this package support JSON marshalling and unmarshalling
Here's an example of how to marshal and unmarshal a single geometry, such as a Point
:
point := geojson.MustPoint([]float64{102.0, 0.5})
pointJSON, err := json.Marshal(point)
if err != nil {
...
}
fmt.Println(string(pointJSON))
pointJSON := `{"type": "Point", "coordinates": [12.4924, 41.8902]}`
var point geojson.Point
err := json.Unmarshal([]byte(pointJSON), &point)
if err != nil {
...
}
fmt.Println(point.Coordinates())
Contributions are welcome! If you'd like to contribute, please submit a pull request or open an issue to discuss changes.
This library is licensed under the MIT License. See LICENSE for details.