paulmach / orb

Types and utilities for working with 2d geometry in Golang
MIT License
910 stars 103 forks source link

Properties inside a FeatureCollection #1

Closed sid6mathur closed 6 years ago

sid6mathur commented 6 years ago

Feature request for adding a Properties map inside the FeatureCollection type so that various metadata can be saved inside while passing the "model" around within the program. https://godoc.org/github.com/paulmach/orb/geojson#FeatureCollection

I understand the GeoJSON standard considers it a "may" feature, but a richer/more expressive in-memory representative would be pretty handy. Also, the marshaller should also serialize it consistent with the Feature implementation, so JavaScript code (e.g in a Mapbox GL JS HTML page) can also access it easily.

Thanks Siddharth

paulmach commented 6 years ago

Hi, according to the geojson spec (https://tools.ietf.org/html/rfc7946) section 7.1 says

"FeatureCollection and Geometry objects, respectively, MUST NOT contain a "geometry" or "properties" member."

I was surprised by this but it does make me against adding it. Plus the properties aren't very type safe so they're really not the way to go. The spec does talk about "foreign members" in section 6.1. Which you can be done by embedding the FeatureCollection like:

rawJSON := []byte(`
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
      "properties": {"prop0": "value0"}
    }
  ],
  "title": "Title of Collection"
}`)

type MyFeatureCollection struct {
    geojson.FeatureCollection
    Title string `json:"title"`
}

fc := &MyFeatureCollection{}
json.Unmarshal(rawJSON, &fc)

fmt.Println(fc.FeatureCollection.Features[0].Geometry)
fmt.Println(fc.Features[0].Geometry)
fmt.Println(fc.Title)

// Output:
// [102 0.5]
// [102 0.5]
// Title of Collection

But that won't really help with every use case, e.g. you want "foreign members" on a feature. In which case you'd have to define your own Feature and FeatureCollection types. On the Pro side, all the complicated stuff is in Marshaling/Unmarshaling the geometries so you could reuse that.

Defining your own types also makes interoperability difficult. turfjs works with geojson which is nice in "flexible" JSON but the Go type system makes that difficult due to the "issues" discussed above. For the orb package I've made everything work on the geometries directly which is different, but I believe can work just as well in practice.

There are many ways to make it so "various metadata can be saved inside while passing the 'model' around within the program" but the best way to do that really depends how you want to read/write/save the "model".

sid6mathur commented 6 years ago

Thank you for the wonderful answer, and it does move me forward. I will use the embedding struct like you suggest, and will solve most of my needs. PS: Apologies for misquoting the GeoJSON spec!