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
{ 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:
{ 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;