Skip to content

Commit 1d804a1

Browse files
authored
NAVAND-1037 add streaming serialisation for DirectionsResponse (#1545)
1 parent d6f1a48 commit 1d804a1

4 files changed

Lines changed: 102 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Mapbox welcomes participation and contributions from everyone.
44

55
### main
6+
- Added `DirectionsResponse.fromJson(Reader)` and `DirectionsResponse.fromJson(Reader, RouteOptions)` to support streaming serialisation of `DirectionsResponse`.
67

78
### v6.11.0 - March 03, 2023
89
- No additional changes

services-core/src/test/java/com/mapbox/core/TestUtils.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
import java.io.ByteArrayOutputStream;
99
import java.io.IOException;
1010
import java.io.InputStream;
11+
import java.io.InputStreamReader;
1112
import java.io.ObjectInputStream;
1213
import java.io.ObjectOutputStream;
1314
import java.io.Serializable;
15+
import java.nio.charset.StandardCharsets;
1416
import java.util.Scanner;
1517

1618
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -28,12 +30,20 @@ public void compareJson(String expectedJson, String actualJson) {
2830
}
2931

3032
protected String loadJsonFixture(String filename) throws IOException {
31-
ClassLoader classLoader = getClass().getClassLoader();
32-
InputStream inputStream = classLoader.getResourceAsStream(filename);
33+
InputStream inputStream = getResourceInputSteam(filename);
3334
Scanner scanner = new Scanner(inputStream, UTF_8.name()).useDelimiter("\\A");
3435
return scanner.hasNext() ? scanner.next() : "";
3536
}
3637

38+
protected InputStreamReader getResourceInputSteamReader(String filename) {
39+
return new InputStreamReader(getResourceInputSteam(filename), StandardCharsets.UTF_8);
40+
}
41+
42+
private InputStream getResourceInputSteam(String filename) {
43+
ClassLoader classLoader = getClass().getClassLoader();
44+
return classLoader.getResourceAsStream(filename);
45+
}
46+
3747
public static <T extends Serializable> byte[] serialize(T obj)
3848
throws IOException {
3949
ByteArrayOutputStream baos = new ByteArrayOutputStream();

services-directions-models/src/main/java/com/mapbox/api/directions/v5/models/DirectionsResponse.java

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import com.mapbox.api.directions.v5.DirectionsAdapterFactory;
1010
import com.mapbox.geojson.Point;
1111
import com.mapbox.geojson.PointAsCoordinatesTypeAdapter;
12+
13+
import java.io.Reader;
1214
import java.util.ArrayList;
1315
import java.util.List;
1416

@@ -139,11 +141,25 @@ public static TypeAdapter<DirectionsResponse> typeAdapter(Gson gson) {
139141
* @since 3.0.0
140142
*/
141143
public static DirectionsResponse fromJson(@NonNull String json) {
142-
GsonBuilder gson = new GsonBuilder();
143-
gson.registerTypeAdapterFactory(DirectionsAdapterFactory.create());
144-
gson.registerTypeAdapter(Point.class, new PointAsCoordinatesTypeAdapter());
145144
// rebuilding to ensure that underlying routes have assigned indices and UUID
146-
return gson.create().fromJson(json, DirectionsResponse.class).toBuilder().build();
145+
return createGson().fromJson(json, DirectionsResponse.class).toBuilder().build();
146+
}
147+
148+
/**
149+
* Deserializes a new instance of this class reading from the specified reader.
150+
* <p>
151+
* Consider using {@link #fromJson(Reader, RouteOptions)} if the result is used with
152+
* downstream consumers of the directions models (like Mapbox Navigation SDK)
153+
* to provide rerouting and route refreshing features.
154+
*
155+
* @param json a reader producing a valid JSON defining a GeoJson Directions Response
156+
* @return a new instance of this class defined by the values passed inside this static factory
157+
* method
158+
* @see #fromJson(Reader, RouteOptions)
159+
*/
160+
public static DirectionsResponse fromJson(@NonNull Reader json) {
161+
// rebuilding to ensure that underlying routes have assigned indices and UUID
162+
return createGson().fromJson(json, DirectionsResponse.class).toBuilder().build();
147163
}
148164

149165
/**
@@ -166,10 +182,7 @@ public static DirectionsResponse fromJson(@NonNull String json) {
166182
@Deprecated
167183
public static DirectionsResponse fromJson(
168184
@NonNull String json, @Nullable RouteOptions routeOptions, @Nullable String requestUuid) {
169-
GsonBuilder gson = new GsonBuilder();
170-
gson.registerTypeAdapterFactory(DirectionsAdapterFactory.create());
171-
gson.registerTypeAdapter(Point.class, new PointAsCoordinatesTypeAdapter());
172-
DirectionsResponse response = gson.create().fromJson(json, DirectionsResponse.class);
185+
DirectionsResponse response = createGson().fromJson(json, DirectionsResponse.class);
173186
if (routeOptions != null) {
174187
response = response.updateWithRequestData(routeOptions);
175188
}
@@ -196,11 +209,33 @@ public static DirectionsResponse fromJson(
196209
* @see RouteOptions#fromJson(String)
197210
*/
198211
public static DirectionsResponse fromJson(
199-
@NonNull String json, @NonNull RouteOptions routeOptions) {
200-
GsonBuilder gson = new GsonBuilder();
201-
gson.registerTypeAdapterFactory(DirectionsAdapterFactory.create());
202-
gson.registerTypeAdapter(Point.class, new PointAsCoordinatesTypeAdapter());
203-
DirectionsResponse response = gson.create().fromJson(json, DirectionsResponse.class);
212+
@NonNull String json,
213+
@NonNull RouteOptions routeOptions
214+
) {
215+
DirectionsResponse response = createGson().fromJson(json, DirectionsResponse.class);
216+
// rebuilding to ensure that underlying routes have assigned indices and UUID
217+
return response.updateWithRequestData(routeOptions);
218+
}
219+
220+
/**
221+
* Deserializes a new instance of this class reading from the specified reader.
222+
* <p>
223+
* The parameter of {@link RouteOptions} that were used to make the original route request
224+
* which might be required by downstream consumers of the directions models
225+
* (like Mapbox Navigation SDK) to provide rerouting and route refreshing features.
226+
*
227+
* @param json a reader producing a valid JSON defining a GeoJson Directions Response
228+
* @param routeOptions options that were used during the original route request
229+
* @return a new instance of this class defined by the values passed inside this static factory
230+
* method
231+
* @see RouteOptions#fromUrl(java.net.URL)
232+
* @see RouteOptions#fromJson(String)
233+
*/
234+
public static DirectionsResponse fromJson(
235+
@NonNull Reader json,
236+
@NonNull RouteOptions routeOptions
237+
) {
238+
DirectionsResponse response = createGson().fromJson(json, DirectionsResponse.class);
204239
// rebuilding to ensure that underlying routes have assigned indices and UUID
205240
return response.updateWithRequestData(routeOptions);
206241
}
@@ -332,4 +367,11 @@ public DirectionsResponse build() {
332367
return autoBuild();
333368
}
334369
}
370+
371+
@NonNull private static Gson createGson() {
372+
GsonBuilder gson = new GsonBuilder();
373+
gson.registerTypeAdapterFactory(DirectionsAdapterFactory.create());
374+
gson.registerTypeAdapter(Point.class, new PointAsCoordinatesTypeAdapter());
375+
return gson.create();
376+
}
335377
}

services-directions-models/src/test/java/com/mapbox/api/directions/v5/models/DirectionsResponseTest.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@
88
import com.mapbox.api.directions.v5.DirectionsCriteria;
99
import com.mapbox.core.TestUtils;
1010
import com.mapbox.geojson.Point;
11+
import org.junit.Test;
1112

1213
import java.io.IOException;
14+
import java.io.InputStreamReader;
15+
import java.util.ArrayList;
1316
import java.util.Arrays;
1417
import java.util.Collections;
1518
import java.util.HashMap;
1619
import java.util.List;
17-
18-
import org.junit.Test;
19-
20-
import java.util.ArrayList;
2120
import java.util.Map;
2221
import java.util.Set;
2322

@@ -83,6 +82,37 @@ public void fromJson_correctlyBuildsFromJson() throws Exception {
8382
assertEquals(1, response.routes().size());
8483
}
8584

85+
@Test
86+
public void deserialization_from_reader() throws Exception {
87+
String testJsonFileName = DIRECTIONS_V5_PRECISION6_FIXTURE;
88+
String jsonText = loadJsonFixture(testJsonFileName);
89+
InputStreamReader jsonReader = getResourceInputSteamReader(testJsonFileName);
90+
91+
DirectionsResponse responseFromReader = DirectionsResponse.fromJson(jsonReader);
92+
DirectionsResponse responseFromText = DirectionsResponse.fromJson(jsonText);
93+
94+
assertEquals(responseFromText, responseFromReader);
95+
}
96+
97+
@Test
98+
public void deserialization_from_reader_with_route_options() throws Exception {
99+
RouteOptions testRouteOptions = RouteOptions.builder()
100+
.profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
101+
.coordinatesList(new ArrayList<Point>() {{
102+
add(Point.fromLngLat(1.0, 1.0));
103+
add(Point.fromLngLat(2.0, 2.0));
104+
}})
105+
.build();
106+
String testJsonFileName = DIRECTIONS_V5_PRECISION6_FIXTURE;
107+
InputStreamReader jsonReader = getResourceInputSteamReader(testJsonFileName);
108+
String jsonText = loadJsonFixture(testJsonFileName);
109+
110+
DirectionsResponse responseFromReader = DirectionsResponse.fromJson(jsonReader, testRouteOptions);
111+
DirectionsResponse responseFromText = DirectionsResponse.fromJson(jsonText, testRouteOptions);
112+
113+
assertEquals(responseFromText, responseFromReader);
114+
}
115+
86116
@Test
87117
public void testToFromJsonWithRealResponse() throws Exception {
88118
Gson gson = new GsonBuilder().create();

0 commit comments

Comments
 (0)