diff --git a/CHANGELOG.md b/CHANGELOG.md index 46194386e5..0769755b39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Releasing is documented in RELEASE.md ### Added - accept [`sac_scale=strolling`](https://wiki.openstreetmap.org/wiki/Key:sac_scale) ([#2149](https://github.com/GIScience/openrouteservice/pull/2149)) - show export endpoint in status ([#2105](https://github.com/GIScience/openrouteservice/issue/2105)) +- documentation on the fields of JSON and GeoJSON responses of the directions endpoint ([#2084](https://github.com/GIScience/openrouteservice/issue/2084)) ### Changed diff --git a/docs/api-reference/endpoints/directions/instruction-types.md b/docs/api-reference/endpoints/directions/instruction-types.md index dd7e7eb9df..7151d38868 100644 --- a/docs/api-reference/endpoints/directions/instruction-types.md +++ b/docs/api-reference/endpoints/directions/instruction-types.md @@ -5,12 +5,12 @@ The following table contains the encoding of the instruction types present in the `type`-field of a directions response in a step of a segment of a route. -JSON-Path in json response: +JSONPath in JSON response: ```jsonpath $.routes[*].segments[*].steps[*].type ``` -JSON-Path in geojson response: +JSONPath in GeoJSON response: ```jsonpath $.features[*].properties.segments[*].steps[*].type ``` diff --git a/docs/api-reference/endpoints/directions/requests-and-return-types.md b/docs/api-reference/endpoints/directions/requests-and-return-types.md index fa94d974ed..e744401ec1 100644 --- a/docs/api-reference/endpoints/directions/requests-and-return-types.md +++ b/docs/api-reference/endpoints/directions/requests-and-return-types.md @@ -18,16 +18,43 @@ Additionally, there is one simple GET request that does not allow advanced reque ### JSON -The **JSON** return type is best suited for further processing. +The **JSON** output format is the most flexible and best suited one for further processing. +Its top level structure consists of three main fields: -### GPX +| Field | Description | +|----------------|---------------------------------------------------------------------------------------------------------------------------------------| +| **`bbox`** | Bounding box `[minLon, minLat, maxLon, maxLat]` covering all of the routes in the response. | +| **`routes`** | List of routes. | +| **`metadata`** | Additional details about the request and routing engine, including `attribution`, `service`, `timestamp`, `query`, and `engine` info. | + +Each of the `routes` entries can contain the following fields. + +| Field | Description | +|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`summary`** | Properties of the route such as total `distance` (m) and `duration` (s). | +| **`segments`** | List of route sections between waypoints, each with `distance`, `duration`, and `steps` containing turn-by-turn navigation instructions if these have been requested. | +| **`bbox`** | Bounding box of the route. | -The **GPX** return type is an XML dialect from openrouteservice based on the [GPS Exchange Format](https://www.topografix.com/gpx.asp) with an own [XML Schema](https://raw.githubusercontent.com/GIScience/openrouteservice-schema/main/gpx/v2/ors-gpx.xsd). -It is a very old standard for lightweight interchange of GPS data and thus being used by hundreds of software programs and Web services. +Furthermore, if route geometry has been requested (which is the default), the following fields are present. + +| Field | Description | +|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **`geometry`** | The path of the route. In JSON it is [encoded](https://developers.google.com/maps/documentation/utilities/polylinealgorithm), while in GeoJSON it is a `LineString` with explicit coordinates. | +| **`way_points`** | Indices of way points corresponding to the `geometry`. | ### GeoJSON -**GeoJSON** is a format for encoding a variety of geographic data structures, see [geojson.org](https://datatracker.ietf.org/doc/html/rfc7946). -It is widely used and can therefore be easily processed or displayed in many applications, e.g. in [QGIS](https://qgis.org/) or on [geojson.io](http://geojson.io/) +**GeoJSON** is a standardized format for encoding a variety of geographic data structures, see [geojson.org](https://datatracker.ietf.org/doc/html/rfc7946). +It is widely used and can therefore be easily processed or displayed in many applications, e.g. in [QGIS](https://qgis.org/) or on [geojson.io](http://geojson.io/). + +The **GeoJSON** output contains the same routing information as its **JSON** counterpart, but organized in slightly different way. + +In the **GeoJSON** format, the route data is structured as a standard **FeatureCollection** where individual routes are represented as `features`. +Each **Feature** includes a `geometry` of type `LineString` and `properties` that contain the same fields as the `routes` elements in the JSON format, i.e. `summary`, `segments`, `way_points`, etc. + +### GPX + +The **GPX** return type is an XML dialect from openrouteservice based on the [GPS Exchange Format](https://www.topografix.com/gpx.asp) with its own [XML Schema](https://raw.githubusercontent.com/GIScience/openrouteservice-schema/main/gpx/v2/ors-gpx.xsd). +It is a very old standard for lightweight interchange of GPS data and thus being used by a wide range of software applications and Web services. -More information about the result types can be found in the [API Playground](https://openrouteservice.org/dev/#/api-docs/directions_service). +More details on the structure of the different return types can be found in the [API Playground](https://openrouteservice.org/dev/#/api-docs/directions_service). diff --git a/docs/api-reference/endpoints/directions/routing-options.md b/docs/api-reference/endpoints/directions/routing-options.md index fd5a433c11..c4bfac25b5 100644 --- a/docs/api-reference/endpoints/directions/routing-options.md +++ b/docs/api-reference/endpoints/directions/routing-options.md @@ -34,7 +34,7 @@ A string array of features to avoid. The available features are : | `steps` | cycling-\*, foot-\*, wheelchair | ### `options.avoid_polygons` -Comprises areas to be avoided for the route. Formatted as [geojson polygon](https://datatracker.ietf.org/doc/html/rfc7946#appendix-A.3) or [geojson multipolygon](https://datatracker.ietf.org/doc/html/rfc7946#appendix-A.6). +Comprises areas to be avoided for the route. Formatted as [GeoJSON polygon](https://datatracker.ietf.org/doc/html/rfc7946#appendix-A.3) or [GeoJSON multipolygon](https://datatracker.ietf.org/doc/html/rfc7946#appendix-A.6). ### `options.profile_params` An object of additional routing parameters for all profiles except `driving-car`: diff --git a/docs/api-reference/endpoints/export/index.md b/docs/api-reference/endpoints/export/index.md index 6e57ecc6d7..2f702363e3 100644 --- a/docs/api-reference/endpoints/export/index.md +++ b/docs/api-reference/endpoints/export/index.md @@ -45,10 +45,10 @@ curl -X 'POST' \ }' ``` -The json response contains nodes and edges in the bounding box relevant for this routing profile. +The JSON response contains nodes and edges in the bounding box relevant for this routing profile. The edge entry `weight` contains the fastest car duration in seconds. -The json response for the above request looks like this: +The JSON response for the above request looks like this: ```json { diff --git a/docs/api-reference/error-codes.md b/docs/api-reference/error-codes.md index 76ff639d49..776cf4d8d7 100644 --- a/docs/api-reference/error-codes.md +++ b/docs/api-reference/error-codes.md @@ -76,7 +76,7 @@ Endpoints. | 4000 | Invalid JSON object in request. | | 4001 | Category or category group ids missing. | | 4002 | Geometry is missing. | -| 4003 | Bounding box and or geojson not present in request. | +| 4003 | Bounding box and or GeoJSON not present in request. | | 4004 | Buffer is missing. | | 4005 | Geometry length does not meet the restrictions. | | 4006 | Unsupported HTTP method. | diff --git a/docs/api-reference/index.md b/docs/api-reference/index.md index d288a8f640..dbd9b3530f 100644 --- a/docs/api-reference/index.md +++ b/docs/api-reference/index.md @@ -21,7 +21,7 @@ Use the form "API Server" on the top left to select and edit "Development Server ![Development server usage](/playground-select-server.png "Development server usage"){ style="display: block; margin: 0 auto"} The responses of your sample requests are visualized on a small map on the bottom right, -but can also be shown as json, table or downloaded as file: +but can also be shown as JSON, table or downloaded as file: ![Example request visualization](/playground-map.png "Example request visualization"){ style="display: block; margin: 0 auto"} ::: warning Hint diff --git a/docs/run-instance/configuration/engine/profiles/build.md b/docs/run-instance/configuration/engine/profiles/build.md index 3bafb308ac..611496fdc3 100644 --- a/docs/run-instance/configuration/engine/profiles/build.md +++ b/docs/run-instance/configuration/engine/profiles/build.md @@ -159,7 +159,7 @@ country borders, compatible with any profile type. | key | type | description | example value | |--------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------| -| boundaries | string | The path to a geojson file containing polygons representing country borders. Ignored if `preprocessed = true` is set. | `borders.geojson.tar.gz` | +| boundaries | string | The path to a GeoJSON file containing polygons representing country borders. Ignored if `preprocessed = true` is set. | `borders.geojson.tar.gz` | | preprocessed | boolean | Indicates whether the source OSM file has been enriched with country data. If set to `true` then country codes are read from `country` node tags rather than being resolved at build time based on geometries provided in `boundaries`. | `true` | | ids | string | Path to a csv file containing a unique id for each country, its local name and its English name | `ids.csv` | | openborders | string | Path to a csv file containing pairs of countries where the borders are open (i.e. Schengen borders) | `openborders.csv` | diff --git a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/IndividualRouteResponse.java b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/IndividualRouteResponse.java index 300803956a..72d5e3d4be 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/IndividualRouteResponse.java +++ b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/IndividualRouteResponse.java @@ -19,13 +19,13 @@ import org.heigit.ors.routing.RouteResult; import org.locationtech.jts.geom.Coordinate; -public class IndividualRouteResponse { +public abstract class IndividualRouteResponse { protected Coordinate[] routeCoordinates; protected boolean includeElevation = false; protected boolean isPtRequest = false; - public IndividualRouteResponse(RouteResult result, RouteRequest request) { + protected IndividualRouteResponse(RouteResult result, RouteRequest request) { if (result.getGeometry() != null) this.routeCoordinates = result.getGeometry(); diff --git a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONBasedIndividualRouteResponse.java b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/JSONBasedIndividualRouteResponse.java similarity index 86% rename from ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONBasedIndividualRouteResponse.java rename to ors-api/src/main/java/org/heigit/ors/api/responses/routing/JSONBasedIndividualRouteResponse.java index 6b0e7b6520..4e5091fcad 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONBasedIndividualRouteResponse.java +++ b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/JSONBasedIndividualRouteResponse.java @@ -13,12 +13,14 @@ * if not, see . */ -package org.heigit.ors.api.responses.routing.json; +package org.heigit.ors.api.responses.routing; import org.heigit.ors.api.requests.routing.RouteRequest; import org.heigit.ors.api.responses.common.boundingbox.BoundingBox; import org.heigit.ors.api.responses.common.boundingbox.BoundingBoxFactory; -import org.heigit.ors.api.responses.routing.IndividualRouteResponse; +import org.heigit.ors.api.responses.routing.json.JSONExtra; +import org.heigit.ors.api.responses.routing.json.JSONLeg; +import org.heigit.ors.api.responses.routing.json.JSONSegment; import org.heigit.ors.common.DistanceUnit; import org.heigit.ors.exceptions.StatusCodeException; import org.heigit.ors.routing.RouteExtraInfo; @@ -32,10 +34,10 @@ import java.util.List; import java.util.Map; -public class JSONBasedIndividualRouteResponse extends IndividualRouteResponse { +public abstract class JSONBasedIndividualRouteResponse extends IndividualRouteResponse { protected BoundingBox bbox; - public JSONBasedIndividualRouteResponse(RouteResult result, RouteRequest request) throws StatusCodeException { + protected JSONBasedIndividualRouteResponse(RouteResult result, RouteRequest request) throws StatusCodeException { super(result, request); if (request.hasUseElevation() && request.getUseElevation()) includeElevation = true; @@ -44,7 +46,7 @@ public JSONBasedIndividualRouteResponse(RouteResult result, RouteRequest request } protected List constructSegments(RouteResult routeResult, RouteRequest request) { - List segments = new ArrayList<>(); + List segments = new ArrayList<>(); for (RouteSegment routeSegment : routeResult.getSegments()) { segments.add(new JSONSegment(routeSegment, request, routeResult.getSummary().getDistance())); } diff --git a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/RouteResponse.java b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/RouteResponse.java index 32dd4fdbec..a85a0228a3 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/RouteResponse.java +++ b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/RouteResponse.java @@ -23,7 +23,7 @@ import java.util.List; -public class RouteResponse { +public abstract class RouteResponse { @JsonIgnore protected RouteResponseInfo responseInformation; @@ -33,7 +33,7 @@ public class RouteResponse { @JsonIgnore protected List routeResults; - public RouteResponse(RouteRequest request, SystemMessageProperties systemMessageProperties, EndpointsProperties endpointsProperties) { + protected RouteResponse(RouteRequest request, SystemMessageProperties systemMessageProperties, EndpointsProperties endpointsProperties) { responseInformation = new RouteResponseInfo(request, systemMessageProperties, endpointsProperties); } @@ -44,8 +44,4 @@ public RouteResponseInfo getResponseInformation() { public BoundingBox getBbox() { return bbox; } - - public List getRouteResults() { - return routeResults; - } } diff --git a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONIndividualRouteResponse.java b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONIndividualRouteResponse.java index 4eba7b4eaf..86511c54ca 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONIndividualRouteResponse.java +++ b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONIndividualRouteResponse.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import org.heigit.ors.api.requests.routing.RouteRequest; -import org.heigit.ors.api.responses.routing.json.JSONBasedIndividualRouteResponse; +import org.heigit.ors.api.responses.routing.JSONBasedIndividualRouteResponse; import org.heigit.ors.api.responses.routing.json.JSONSegment; import org.heigit.ors.exceptions.StatusCodeException; import org.heigit.ors.geojson.GeometryJSON; diff --git a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONRouteResponse.java b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONRouteResponse.java index b3004f9e93..58689926c8 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONRouteResponse.java +++ b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/geojson/GeoJSONRouteResponse.java @@ -64,8 +64,8 @@ public GeoJSONRouteResponse(RouteResult[] routeResults, RouteRequest request, Sy } @JsonProperty("features") - public List getRoutes() { - return routeResults; + public GeoJSONIndividualRouteResponse[] getRoutes() { + return routeResults.toArray(new GeoJSONIndividualRouteResponse[0]); } @JsonProperty("metadata") diff --git a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONIndividualRouteResponse.java b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONIndividualRouteResponse.java index 445e95e0fc..140f339790 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONIndividualRouteResponse.java +++ b/ors-api/src/main/java/org/heigit/ors/api/responses/routing/json/JSONIndividualRouteResponse.java @@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import org.heigit.ors.api.requests.routing.RouteRequest; import org.heigit.ors.api.responses.common.boundingbox.BoundingBoxFactory; +import org.heigit.ors.api.responses.routing.JSONBasedIndividualRouteResponse; import org.heigit.ors.common.DistanceUnit; import org.heigit.ors.exceptions.StatusCodeException; import org.heigit.ors.routing.RouteExtraInfo;