Search code examples
androidjsonnavigationmapboxmapbox-android

How to convert JSON to DirectionsRoute


I'm developing a simple navigator with mapbox API for Android. I'm creating some routes using https://docs.mapbox.com/playground/directions/ playground and i would like to use the generated JSON to generate a DirectionsRoute object. So i call DirectionsRoute.fromJson() but when i do it, the application crashes with this error:

E/Mbgl-MapChangeReceiver: Exception in onDidFinishLoadingStyle
java.lang.NullPointerException: Null distance
    at com.mapbox.api.directions.v5.models.$AutoValue_DirectionsRoute.<init>($AutoValue_DirectionsRoute.java:45)
    at com.mapbox.api.directions.v5.models.AutoValue_DirectionsRoute.<init>(AutoValue_DirectionsRoute.java:27)
    at com.mapbox.api.directions.v5.models.AutoValue_DirectionsRoute$GsonTypeAdapter.read(AutoValue_DirectionsRoute.java:260)
    at com.mapbox.api.directions.v5.models.AutoValue_DirectionsRoute$GsonTypeAdapter.read(AutoValue_DirectionsRoute.java:30)
    at com.google.gson.Gson.fromJson(Gson.java:932)
    at com.google.gson.Gson.fromJson(Gson.java:897)
    at com.google.gson.Gson.fromJson(Gson.java:846)
    at com.google.gson.Gson.fromJson(Gson.java:817)
    at com.mapbox.api.directions.v5.models.DirectionsRoute.fromJson(DirectionsRoute.java:172)
    at eu.mediator.hmi.cluster2.navigator.Nav.getDirectionsRoute(Nav.kt:108)
    at eu.mediator.hmi.cluster2.navigator.Nav.access$getDirectionsRoute(Nav.kt:15)
    at eu.mediator.hmi.cluster2.navigator.Nav$route$2.invoke(Nav.kt:19)
    at eu.mediator.hmi.cluster2.navigator.Nav$route$2.invoke(Nav.kt:19)
    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
    at eu.mediator.hmi.cluster2.navigator.Nav.getRoute(Nav.kt:19)
    at eu.mediator.hmi.cluster2.navigator.Nav.onNavigationReady(Nav.kt:83)
    at com.mapbox.navigation.ui.NavigationView.updateNavigationReadyListeners(NavigationView.java:701)
    at com.mapbox.navigation.ui.NavigationView.lambda$onMapReady$0$NavigationView(NavigationView.java:261)
    at com.mapbox.navigation.ui.-$$Lambda$NavigationView$cQ4pEaxGsKIc0JZPsHECDoNZqgE.onStyleLoaded(Unknown Source:4)
    at com.mapbox.mapboxsdk.maps.MapboxMap.notifyStyleLoaded(MapboxMap.java:963)
    at com.mapbox.mapboxsdk.maps.MapboxMap.onFinishLoadingStyle(MapboxMap.java:225)
    at com.mapbox.mapboxsdk.maps.MapView$MapCallback.onDidFinishLoadingStyle(MapView.java:1383)
    at com.mapbox.mapboxsdk.maps.MapChangeReceiver.onDidFinishLoadingStyle(MapChangeReceiver.java:198)
    at com.mapbox.mapboxsdk.maps.NativeMapView.onDidFinishLoadingStyle(NativeMapView.java:1166)
    at android.os.MessageQueue.nativePollOnce(Native Method)
    at android.os.MessageQueue.next(MessageQueue.java:326)
    at android.os.Looper.loop(Looper.java:160)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

This is an example of the json I'm trying to parse:

{
  "routes": [
    {
      "weight_name": "auto",
      "weight": 296.434,
      "duration": 220.762,
      "distance": 706.383,
      "legs": [
        {
          "admins": [{"iso_3166_1_alpha3": "USA", "iso_3166_1": "US"}],
          "weight": 296.434,
          "duration": 220.762,
          "steps": [
            {
              "intersections": [
                {
                  "entry": [true],
                  "bearings": [299],
                  "duration": 1.309,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 1.539,
                  "geometry_index": 0,
                  "location": [-73.992199, 40.734505]
                },
                {
                  "entry": [false, true],
                  "in": 0,
                  "bearings": [119, 299],
                  "duration": 58.966,
                  "turn_weight": 2,
                  "turn_duration": 2.021,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 1,
                  "weight": 68.911,
                  "geometry_index": 1,
                  "location": [-73.992255, 40.734529]
                },
                {
                  "bearings": [119, 299],
                  "entry": [false, true],
                  "in": 0,
                  "turn_weight": 2,
                  "turn_duration": 0.021,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 1,
                  "geometry_index": 2,
                  "location": [-73.994055, 40.735287]
                }
              ],
              "maneuver": {
                "type": "depart",
                "instruction": "Drive northwest on East 13th Street.",
                "bearing_after": 299,
                "bearing_before": 0,
                "location": [-73.992199, 40.734505]
              },
              "name": "East 13th Street",
              "duration": 62.26,
              "distance": 185.82,
              "driving_side": "right",
              "weight": 74.757,
              "mode": "driving",
              "geometry": "qqfulAl_cclCo@nBkn@noBs@|B"
            },
            {
              "intersections": [
                {
                  "entry": [false, true],
                  "in": 0,
                  "bearings": [119, 210],
                  "duration": 8.377,
                  "turn_weight": 22.5,
                  "turn_duration": 7.395,
                  "mapbox_streets_v8": {"class": "secondary"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 1,
                  "weight": 23.654,
                  "geometry_index": 3,
                  "location": [-73.994118, 40.735313]
                },
                {
                  "entry": [false, true],
                  "in": 0,
                  "bearings": [30, 210],
                  "duration": 11.134,
                  "turn_weight": 2,
                  "turn_duration": 0.007,
                  "mapbox_streets_v8": {"class": "secondary"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 1,
                  "weight": 15.075,
                  "geometry_index": 4,
                  "location": [-73.994156, 40.735263]
                },
                {
                  "bearings": [30, 210],
                  "entry": [false, true],
                  "in": 0,
                  "turn_weight": 2,
                  "turn_duration": 0.007,
                  "mapbox_streets_v8": {"class": "secondary"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 1,
                  "geometry_index": 5,
                  "location": [-73.994562, 40.734732]
                }
              ],
              "maneuver": {
                "type": "turn",
                "instruction": "Turn left onto 5th Avenue.",
                "modifier": "left",
                "bearing_after": 210,
                "bearing_before": 299,
                "location": [-73.994118, 40.735313]
              },
              "name": "5th Avenue",
              "duration": 20.663,
              "distance": 81,
              "driving_side": "right",
              "weight": 42.074,
              "mode": "driving",
              "geometry": "adhulAjwfclCbBjAd`@jXdBlA"
            },
            {
              "intersections": [
                {
                  "entry": [false, true],
                  "in": 0,
                  "bearings": [30, 121],
                  "duration": 9.332,
                  "turn_weight": 12.5,
                  "turn_duration": 7.275,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 1,
                  "weight": 14.917,
                  "geometry_index": 6,
                  "location": [-73.994601, 40.734681]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [118, 301],
                  "duration": 1.051,
                  "turn_weight": 2,
                  "turn_duration": 0.022,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 3.209,
                  "geometry_index": 7,
                  "location": [-73.994524, 40.734646]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 298],
                  "duration": 39.865,
                  "turn_weight": 2,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 48.832,
                  "geometry_index": 8,
                  "location": [-73.994484, 40.73463]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 2.065,
                  "turn_weight": 2,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 4.417,
                  "geometry_index": 9,
                  "location": [-73.992878, 40.733958]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 4.626,
                  "turn_weight": 2,
                  "turn_duration": 2.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 5.076,
                  "geometry_index": 10,
                  "location": [-73.992792, 40.733922]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 47.135,
                  "turn_weight": 2,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 57.375,
                  "geometry_index": 11,
                  "location": [-73.992714, 40.733889]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 3.608,
                  "turn_weight": 2,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 6.23,
                  "geometry_index": 12,
                  "location": [-73.991224, 40.73326]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 4.5,
                  "turn_weight": 2,
                  "turn_duration": 2.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 4.928,
                  "geometry_index": 13,
                  "location": [-73.991114, 40.733214]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 14.962,
                  "turn_weight": 2,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 19.571,
                  "geometry_index": 14,
                  "location": [-73.991019, 40.733174]
                },
                {
                  "entry": [true, false],
                  "in": 1,
                  "bearings": [119, 299],
                  "duration": 7.762,
                  "turn_weight": 0.5,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "weight": 9.611,
                  "geometry_index": 15,
                  "location": [-73.990465, 40.732939]
                },
                {
                  "bearings": [119, 299],
                  "entry": [true, false],
                  "in": 1,
                  "turn_weight": 2,
                  "turn_duration": 0.008,
                  "mapbox_streets_v8": {"class": "street"},
                  "is_urban": true,
                  "admin_index": 0,
                  "out": 0,
                  "geometry_index": 16,
                  "location": [-73.990173, 40.732817]
                }
              ],
              "maneuver": {
                "type": "turn",
                "instruction": "Turn left onto East 12th Street.",
                "modifier": "left",
                "bearing_after": 121,
                "bearing_before": 210,
                "location": [-73.994601, 40.734681]
              },
              "name": "East 12th Street",
              "duration": 137.839,
              "distance": 439.563,
              "driving_side": "right",
              "weight": 179.603,
              "mode": "driving",
              "geometry": "q|fulApugclCdAyC^oA~h@kcBfAkD`A{Chf@c|AzA{EnA}DtMsa@rFgQ`@oAx@kC"
            },
            {
              "intersections": [
                {
                  "bearings": [299],
                  "entry": [true],
                  "in": 0,
                  "admin_index": 0,
                  "geometry_index": 18,
                  "location": [-73.990063, 40.732771]
                }
              ],
              "maneuver": {
                "type": "arrive",
                "instruction": "Your destination is on the right.",
                "modifier": "right",
                "bearing_after": 0,
                "bearing_before": 119,
                "location": [-73.990063, 40.732771]
              },
              "name": "East 12th Street",
              "duration": 0,
              "distance": 0,
              "driving_side": "right",
              "weight": 0,
              "mode": "driving",
              "geometry": "eeculA|y~blC??"
            }
          ],
          "distance": 706.383,
          "summary": "East 13th Street, East 12th Street"
        }
      ],
      "geometry": "qqfulAl_cclCoq@|vBnf@d]jvBszG"
    }
  ],
  "waypoints": [
    {
      "distance": 2.275,
      "name": "East 13th Street",
      "location": [-73.992199, 40.734505]
    },
    {
      "distance": 4.846,
      "name": "East 12th Street",
      "location": [-73.990063, 40.732771]
    }
  ],
  "code": "Ok",
  "uuid": "iN7DOXpeBlZLl3bHqiFcXZinCTs9_4miufia3aF9gVodZF3QZ-c0lQ=="
}

Solution

  • The response from the mapbox API is not DirectionsRoute. It is DirectionsResponse, a structure that looks like this:

    {
        "routes":[ ... ],
        "waypoints":[ ... ],
        "code":"Ok",
        "uuid":"iN7DOXpeBlZLl3bHqiFcXZinCTs9_4miufia3aF9gVodZF3QZ-c0lQ=="
    }
    

    So you can't parse this using DirectionsRoute.fromJson()

    The response contains a list of DirectionsRoutes, in the "routes" property. Usually the first one is the one that is used. To parse this use

    directionsResponse = DirectionsResponse.fromJson();
    

    and then you can get the first route in the response like this:

    DirectionsRoute route = directionsResponse.routes().get(0);