diff --git a/services-directions-models/src/main/java/com/mapbox/api/directions/v5/models/DirectionsResponse.java b/services-directions-models/src/main/java/com/mapbox/api/directions/v5/models/DirectionsResponse.java index 3350be797..bb01efb46 100644 --- a/services-directions-models/src/main/java/com/mapbox/api/directions/v5/models/DirectionsResponse.java +++ b/services-directions-models/src/main/java/com/mapbox/api/directions/v5/models/DirectionsResponse.java @@ -9,6 +9,14 @@ import com.mapbox.api.directions.v5.DirectionsAdapterFactory; import com.mapbox.geojson.Point; import com.mapbox.geojson.PointAsCoordinatesTypeAdapter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -146,6 +154,48 @@ public static DirectionsResponse fromJson(@NonNull String json) { return gson.create().fromJson(json, DirectionsResponse.class).toBuilder().build(); } + public static DirectionsResponse fromJson(@NonNull ByteBuffer json, Charset charsets) { + GsonBuilder gson = new GsonBuilder(); + gson.registerTypeAdapterFactory(DirectionsAdapterFactory.create()); + gson.registerTypeAdapter(Point.class, new PointAsCoordinatesTypeAdapter()); + // rebuilding to ensure that underlying routes have assigned indices and UUID + + InputStream is = new ByteBufferBackedInputStream(json); + InputStreamReader r = new InputStreamReader(is, charsets); + return gson.create().fromJson(r, DirectionsResponse.class).toBuilder().build(); + } + + private static class ByteBufferBackedInputStream extends InputStream { + + ByteBuffer buf; + + public ByteBufferBackedInputStream(ByteBuffer buf) { + this.buf = buf; + } + + public synchronized int read() throws IOException { + if (!buf.hasRemaining()) { + return -1; + } + return buf.get() & 0xFF; + } + + @Override + public int available() throws IOException { + return buf.remaining(); + } + + public synchronized int read(byte[] bytes, int off, int len) throws IOException { + if (!buf.hasRemaining()) { + return -1; + } + + len = Math.min(len, buf.remaining()); + buf.get(bytes, off, len); + return len; + } + } + /** * Create a new instance of this class by passing in a formatted valid JSON String. *

diff --git a/services-directions-models/src/test/java/com/mapbox/api/directions/v5/models/DirectionsResponseTest.java b/services-directions-models/src/test/java/com/mapbox/api/directions/v5/models/DirectionsResponseTest.java index 80d8dd304..6575d8824 100644 --- a/services-directions-models/src/test/java/com/mapbox/api/directions/v5/models/DirectionsResponseTest.java +++ b/services-directions-models/src/test/java/com/mapbox/api/directions/v5/models/DirectionsResponseTest.java @@ -1,5 +1,6 @@ package com.mapbox.api.directions.v5.models; +import androidx.annotation.NonNull; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; @@ -10,6 +11,9 @@ import com.mapbox.geojson.Point; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -83,6 +87,25 @@ public void fromJson_correctlyBuildsFromJson() throws Exception { assertEquals(1, response.routes().size()); } + @Test + public void deserialization_from_byte_buffer() throws Exception { + String textJson = loadJsonFixture(DIRECTIONS_V5_PRECISION6_FIXTURE); + ByteBuffer buffer = putTextToDirectByteBuffer(textJson, StandardCharsets.UTF_8); + + DirectionsResponse responseFromBuffer = DirectionsResponse.fromJson(buffer, StandardCharsets.UTF_8); + DirectionsResponse responseFromText = DirectionsResponse.fromJson(textJson); + + assertEquals(responseFromText, responseFromBuffer); + } + + @NonNull private ByteBuffer putTextToDirectByteBuffer(String textJson, Charset charset) { + byte[] json = textJson.getBytes(charset); + ByteBuffer buffer = ByteBuffer.allocateDirect(json.length); + buffer.put(json); + buffer.position(0); + return buffer; + } + @Test public void testToFromJsonWithRealResponse() throws Exception { Gson gson = new GsonBuilder().create();