Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8c69ad4
Use primitive array in Point instead of List
jush Jan 23, 2026
16a474d
Use flat structure for LineString data
jush Jan 25, 2026
03133c4
Use class to store flatten list of points
jush Jan 25, 2026
8cd1b9c
Rename PrimitiveCoordinateContainer to FlattenedCoordinateContainer
jush Jan 25, 2026
c182c29
Minor refactor FlattenListOfPoints
jush Jan 25, 2026
b2754df
Add missing Keep to FlattenedCoordinateContainer
jush Jan 25, 2026
b107ac9
Convert MultiPoint to use flatten structure
jush Jan 25, 2026
c5cdda7
Remove unused ListOfPointCoordinatesTypeAdapter.java
jush Jan 25, 2026
981ea48
Minor rename and fix empty list of points
jush Jan 25, 2026
a6e7feb
Small javadoc fixes
jush Jan 26, 2026
a715c38
Fix code style
jush Jan 26, 2026
cfa95b9
Better names when reading point from JSON
jush Jan 26, 2026
8db98e8
Fix order of lng,lat in various names and improved tests
jush Jan 26, 2026
eb96721
Improve reading list of points from JSON
jush Jan 26, 2026
63fc157
Expose LineString constructor with FlattenListOfPoints
jush Jan 26, 2026
6d564fb
Added encode/decode to PolylineUtils
jush Jan 26, 2026
b0fb8f7
Build LineString.toString using the FlattenListOfPoints
jush Jan 26, 2026
c3d7bab
Code style fixes
jush Jan 27, 2026
e264d6f
Use flattenListOfPoints for the `toString`
jush Jan 27, 2026
e375321
Update services-geojson/src/main/java/com/mapbox/geojson/FlattenListO…
jush Jan 27, 2026
aa51c39
PolylineUtils#decodeToFlattenListOfPoints returns double[]
jush Jan 29, 2026
9c85c7d
Fixed TurfMiscTest tests
jush Jan 29, 2026
be6d8b8
Add FlattenListOfPoints unit tests
jush Jan 30, 2026
ef71786
Add size for FlattenListOfPoints
jush Jan 30, 2026
ffde2c7
Add more shifter test for default one
jush Jan 30, 2026
2ee2d04
Read JSON with extra coordinate values
jush Jan 30, 2026
a3c8f4c
Test initial capacity for the line string JSON logic
jush Jan 30, 2026
b978c91
Changes to docs and minor API alignments
jush Jan 30, 2026
6750ed3
Added changelog entries
jush Jan 30, 2026
1007965
Squeezed a few more bytes from Point
jush Jan 30, 2026
164c42d
Revert "Squeezed a few more bytes from Point"
jush Jan 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Mapbox welcomes participation and contributions from everyone.

### main
- Added `DirectionsRefreshResponse#fromJson(Reader)`, a static factory method that deserializes a `DirectionsRefreshResponse` from a `java.io.Reader`.
- Added `FlattenListOfPoints` to hold a list of points in a more memory-efficient way.
- Deprecate `LineString#coordinates()` and `Point#coordinates()`. It's encouraged to use the new `flattenCoordinates()` methods.


### v7.9.0 - November 20, 2025

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
package com.mapbox.geojson;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.mapbox.geojson.exception.GeoJsonException;
import com.mapbox.geojson.shifter.CoordinateShifterManager;
import com.mapbox.geojson.utils.GeoJsonUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* Base class for converting {@code T} instance of coordinates to JSON and
* JSON to instance of {@code T}.
* Base class for converting {@code T} instance of coordinates to JSON and
* JSON to instance of {@code T}.
*
* @param <T> Type of coordinates
* @since 4.6.0
Expand All @@ -25,25 +23,19 @@
abstract class BaseCoordinatesTypeAdapter<T> extends TypeAdapter<T> {


protected void writePoint(JsonWriter out, Point point) throws IOException {
protected void writePoint(JsonWriter out, Point point) throws IOException {
if (point == null) {
return;
}
writePointList(out, point.coordinates());
writePointList(out, point.flattenCoordinates());
}

protected Point readPoint(JsonReader in) throws IOException {

List<Double> coordinates = readPointList(in);
if (coordinates != null && coordinates.size() > 1) {
return new Point("Point",null, coordinates);
}

throw new GeoJsonException(" Point coordinates should be non-null double array");
return new Point("Point", null, readPointList(in));
}


protected void writePointList(JsonWriter out, List<Double> value) throws IOException {
protected void writePointList(JsonWriter out, double[] value) throws IOException {

if (value == null) {
return;
Expand All @@ -52,38 +44,52 @@ protected void writePointList(JsonWriter out, List<Double> value) throws IOExcep
out.beginArray();

// Unshift coordinates
List<Double> unshiftedCoordinates =
CoordinateShifterManager.getCoordinateShifter().unshiftPoint(value);
double[] unshiftedCoordinates = CoordinateShifterManager.getCoordinateShifter()
.unshiftPointArray(value);

out.value(GeoJsonUtils.trim(unshiftedCoordinates.get(0)));
out.value(GeoJsonUtils.trim(unshiftedCoordinates.get(1)));
out.value(GeoJsonUtils.trim(unshiftedCoordinates[0]));
out.value(GeoJsonUtils.trim(unshiftedCoordinates[1]));

// Includes altitude
if (value.size() > 2) {
out.value(unshiftedCoordinates.get(2));
if (value.length > 2) {
out.value(unshiftedCoordinates[2]);
}
out.endArray();
}

protected List<Double> readPointList(JsonReader in) throws IOException {

@NonNull
protected double[] readPointList(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
throw new NullPointerException();
}

List<Double> coordinates = new ArrayList<Double>(3);
double lon;
double lat;
double altitude;
in.beginArray();
while (in.hasNext()) {
coordinates.add(in.nextDouble());
if (in.hasNext()) {
lon = in.nextDouble();
} else {
throw new IndexOutOfBoundsException("Point coordinates should contain at least two values");
}
in.endArray();

if (coordinates.size() > 2) {
return CoordinateShifterManager.getCoordinateShifter()
.shiftLonLatAlt(coordinates.get(0), coordinates.get(1), coordinates.get(2));
if (in.hasNext()) {
lat = in.nextDouble();
} else {
throw new IndexOutOfBoundsException("Point coordinates should contain at least two values");
}
if (in.hasNext()) {
altitude = in.nextDouble();
// Consume any extra value but don't store it
while (in.hasNext()) {
in.skipValue();
}
in.endArray();
return CoordinateShifterManager.getCoordinateShifter().shift(lon, lat, altitude);
} else {
in.endArray();
return CoordinateShifterManager.getCoordinateShifter().shift(lon, lat);
}
return CoordinateShifterManager.getCoordinateShifter()
.shiftLonLat(coordinates.get(0), coordinates.get(1));

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,68 @@
*
* @param <G> Geometry
* @param <T> Type of coordinates
* @param <A> The type of coordinates adapter
* @since 4.6.0
*/
@Keep
abstract class BaseGeometryTypeAdapter<G, T> extends TypeAdapter<G> {
abstract class BaseGeometryTypeAdapter<G, T, A> extends TypeAdapter<G> {

private volatile TypeAdapter<String> stringAdapter;
private volatile TypeAdapter<BoundingBox> boundingBoxAdapter;
private volatile TypeAdapter<T> coordinatesAdapter;
private final BaseCoordinatesTypeAdapter<A> coordinatesAdapter;

private final Gson gson;

BaseGeometryTypeAdapter(Gson gson, TypeAdapter<T> coordinatesAdapter) {
BaseGeometryTypeAdapter(Gson gson, BaseCoordinatesTypeAdapter<A> coordinatesAdapter) {
if (coordinatesAdapter == null) {
throw new GeoJsonException("Coordinates type adapter is null");
}
this.gson = gson;
this.coordinatesAdapter = coordinatesAdapter;
this.boundingBoxAdapter = new BoundingBoxTypeAdapter();
}

public void writeCoordinateContainer(JsonWriter jsonWriter, CoordinateContainer<T> object)
public void writeFlattenedCoordinateContainer(
JsonWriter jsonWriter,
FlattenedCoordinateContainer<T, A> object
) throws IOException {
if (object == null) {
jsonWriter.nullValue();
return;
}
writeCommon(jsonWriter, object);
jsonWriter.name("coordinates");
coordinatesAdapter.write(jsonWriter, object.flattenCoordinates());
jsonWriter.endObject();
}

public void writeCoordinateContainer(JsonWriter jsonWriter, CoordinateContainer<A> object)
throws IOException {
if (object == null) {
jsonWriter.nullValue();
return;
}

writeCommon(jsonWriter, object);

jsonWriter.name("coordinates");
if (object.coordinates() == null) {
jsonWriter.nullValue();
} else {
coordinatesAdapter.write(jsonWriter, object.coordinates());
}

jsonWriter.endObject();
}

/**
* Write the common part of the coordinate container: "type" and "bbox".
*/
private void writeCommon(
JsonWriter jsonWriter,
@SuppressWarnings("rawtypes")
CoordinateContainer object
) throws IOException {
jsonWriter.beginObject();
jsonWriter.name("type");
if (object.type() == null) {
Expand All @@ -64,17 +103,6 @@ public void writeCoordinateContainer(JsonWriter jsonWriter, CoordinateContainer<
}
boundingBoxAdapter.write(jsonWriter, object.bbox());
}
jsonWriter.name("coordinates");
if (object.coordinates() == null) {
jsonWriter.nullValue();
} else {
TypeAdapter<T> coordinatesAdapter = this.coordinatesAdapter;
if (coordinatesAdapter == null) {
throw new GeoJsonException("Coordinates type adapter is null");
}
coordinatesAdapter.write(jsonWriter, object.coordinates());
}
jsonWriter.endObject();
}

public CoordinateContainer<T> readCoordinateContainer(JsonReader jsonReader) throws IOException {
Expand All @@ -86,7 +114,7 @@ public CoordinateContainer<T> readCoordinateContainer(JsonReader jsonReader) thr
jsonReader.beginObject();
String type = null;
BoundingBox bbox = null;
T coordinates = null;
A coordinates = null;

while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
Expand Down Expand Up @@ -114,7 +142,7 @@ public CoordinateContainer<T> readCoordinateContainer(JsonReader jsonReader) thr
break;

case "coordinates":
TypeAdapter<T> coordinatesAdapter = this.coordinatesAdapter;
TypeAdapter<A> coordinatesAdapter = this.coordinatesAdapter;
if (coordinatesAdapter == null) {
throw new GeoJsonException("Coordinates type adapter is null");
}
Expand All @@ -133,5 +161,5 @@ public CoordinateContainer<T> readCoordinateContainer(JsonReader jsonReader) thr

abstract CoordinateContainer<T> createCoordinateContainer(String type,
BoundingBox bbox,
T coordinates);
A coordinates);
}
Loading