Skip to content

Instantly share code, notes, and snippets.

@dschep
Last active June 12, 2019 18:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dschep/c987bead83b9c0513c32344d38e4fdf4 to your computer and use it in GitHub Desktop.
Save dschep/c987bead83b9c0513c32344d38e4fdf4 to your computer and use it in GitHub Desktop.
JMSEPath Expressions to turn GBFS into GeoJSON

GBFS Bikes to GeoJSON

This creates a feature collection from the bikes endpoint of a GBFS service, such as JUMP DC's feed: https://dc.jumpmobility.com/opendata/free_bike_status.json

{type: `FeatureCollection`, features: data.bikes[*].{id: bike_id, geometry: {type: `Point`, coordinates: [lon, lat]}, properties: @}}

Example

GBFS Input:

{
  "last_updated": 1518889202,
  "ttl": 60,
  "data": {
    "bikes": [
      {
        "bike_id": "bike_17237",
        "name": "JUMP DC-0239",
        "lon": -76.9832,
        "lat": 38.946725,
        "is_reserved": 0,
        "is_disabled": 0,
        "jump_ebike_battery_level": "52%"
      }
    ]
  }
}

GeoJSON output:

{
  "type": "FeatureCollection",
  "features": [
    {
      "id": "bike_17237",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -76.9832,
          38.946725
        ]
      },
      "properties": {
        "bike_id": "bike_17237",
        "name": "JUMP DC-0239",
        "lon": -76.9832,
        "lat": 38.946725,
        "is_reserved": 0,
        "is_disabled": 0,
        "jump_ebike_battery_level": "52%"
      }
    }
  ]
}

GBFS Station information to GeoJSON

This creates a feature collection from the bikes endpoint of a GBFS service, such as CaBi's feed: https://gbfs.capitalbikeshare.com/gbfs/en/station_information.json

{type: `FeatureCollection`, features: data.stations[*].{id: station_id, geometry: {type: `Point`, coordinates: [lon, lat]}, properties: @}}

This isn't very useful with out Station status since this doesn't contain info about number of bikes.

Example

GBFS input:

{
  "last_updated": 1518889367,
  "ttl": 10,
  "data": {
    "stations": [
      {
        "station_id": "1",
        "name": "Eads St & 15th St S",
        "short_name": "31000",
        "lat": 38.858971,
        "lon": -77.05323,
        "region_id": 41,
        "rental_methods": [
          "KEY",
          "CREDITCARD"
        ],
        "capacity": 15,
        "rental_url": "http://app.capitalbikeshare.com/vIiR/zVsfTIsOTF?station_id=1",
        "eightd_has_key_dispenser": false
      }
    ]
  }
}

GeoJSON output:

{
  "type": "FeatureCollection",
  "features": [
    {
      "id": "1",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -77.05323,
          38.858971
        ]
      },
      "properties": {
        "station_id": "1",
        "name": "Eads St & 15th St S",
        "short_name": "31000",
        "lat": 38.858971,
        "lon": -77.05323,
        "region_id": 41,
        "rental_methods": [
          "KEY",
          "CREDITCARD"
        ],
        "capacity": 15,
        "rental_url": "http://app.capitalbikeshare.com/vIiR/zVsfTIsOTF?station_id=1",
        "eightd_has_key_dispenser": false
      }
    }
  ]
}

GBFS Station status to GeoJSON

This creates a feature collection from the bikes endpoint of a GBFS service, such as CaBi's feed: https://gbfs.capitalbikeshare.com/gbfs/en/station_status.json

{type: `FeatureCollection`, features: data.stations[*].{id: station_id, properties: @}}

This isn't very useful with out Station information since this doesn't contain the location of the station.

Example

GBFS input:

{
  "last_updated": 1518889523,
  "ttl": 10,
  "data": {
    "stations": [
      {
        "station_id": "1",
        "num_bikes_available": 5,
        "num_bikes_disabled": 0,
        "num_docks_available": 10,
        "num_docks_disabled": 0,
        "is_installed": 1,
        "is_renting": 1,
        "is_returning": 1,
        "last_reported": 1518885345,
        "eightd_has_available_keys": false
      }
    ]
  }
}

GeoJSON output:

{
  "type": "FeatureCollection",
  "features": [
    {
      "id": "1",
      "properties": {
        "station_id": "1",
        "num_bikes_available": 5,
        "num_bikes_disabled": 0,
        "num_docks_available": 10,
        "num_docks_disabled": 0,
        "is_installed": 1,
        "is_renting": 1,
        "is_returning": 1,
        "last_reported": 1518885345,
        "eightd_has_available_keys": false
      }
    }
  ]
}

JavaScript example merging the two station objects

Promise.all([fetch('https://gbfs.capitalbikeshare.com/gbfs/en/station_information.json', {cors: true}),
             fetch('https://gbfs.capitalbikeshare.com/gbfs/en/station_status.json', {cors: true})])
  .then(resps => Promise.all(resps.map(resp => resp.json())))
  .then(([info, stat]) => [
    jmespath.search(info, '{type: `FeatureCollection`, features: data.stations[*].{id: station_id, geometry: {type: `Point`, coordinates: [lon, lat]}, properties: @}}'),
    jmespath.search(stat, '{type: `FeatureCollection`, features: data.stations[*].{id: station_id, properties: @}}')])
  .then(([infoGeoJSON, statGeoJSON]) => {
    const statMap = new Map(statGeoJSON.features.map(({id, properties}) => [id, properties]));
    infoGeoJSON.features = infoGeoJSON.features.map(({id, geometry, properties}) => ({
      id,
      geometry,
      properties: Object.assign({}, properties, statMap.get(id)),
    }));
    return infoGeoJSON;
  })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment