There is a question here that is similar to my question but not exactly what I'm looking for.
I've a JSON response from a webservice, let's say this JSON response:
{
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 45.5017123,
"lng" : -73.5672184
},
"southwest" : {
"lat" : 43.6533103,
"lng" : -79.3827675
}
},
"copyrights" : "Dados do mapa ©2015 Google",
"legs" : [
{
"distance" : {
"text" : "541 km",
"value" : 540536
},
"duration" : {
"text" : "5 horas 18 min.",
"value" : 19058
},
"end_address" : "Montreal, QC, Canada",
"end_location" : {
"lat" : 45.5017123,
"lng" : -73.5672184
},
"start_address" : "Toronto, ON, Canada",
"start_location" : {
"lat" : 43.6533103,
"lng" : -79.3827675
},
(...)
In this JSON I' just interested on the distance
object. My question is, how can I ignore all the other fields?
I tried to build my object starting from legs
, as it is the first non repetitive object name from distance
to the root.
Here's my object:
public class MyObject {
public ArrayList<Distance> legs;
public static class Distance {
public String text;
public String value;
}
}
but the ArrayList legs
is always null
.
How can I accomplish this? Ignore fields to the left from the pretended json field.
I think that the philosophy of Gson is to map the Json structure to an objects graph. So in your case I would probably create all the needed java objects to map correctly the json structure. In addition of that, maybe one day you will need some other information of the response, so it will be easier to do the evolution. Something like that (the proper way I think):
class RouteResponse {
private List<Route> routes;
}
class Route {
private List<Bound> bounds;
private String copyrights;
private List<Leg> legs;
}
class Leg {
private Distance distance;
private Duration duration;
private String endAddress;
...
}
class TextValue {
private String text;
private String value;
}
class Distance extends TextValue {
}
// And so on
And I would use an ExclusionStrategy to have light objects and to have only the fields I'm interested in. It sounds to me like the proper way to do that.
Now if you really want to retrieve only the list of distances, I'm sure you can do that with a custom TypeAdapter and TypeAdapterFactory.
Something like that (the bad way :-)):
The objects to map the response:
public class RouteResponse {
private List<Distance> distances;
// add getters / setters
}
public class Distance {
private String text;
private String value;
// add getters / setters
}
The factory that instantiates our adapter (With a reference to the Gson
object, so the adapter can retrieve delegates) :
public class RouteResponseTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == RouteResponse.class) {
return (TypeAdapter<T>)new RouteResponseTypeAdapter(gson);
}
return null;
}
}
And the type adapter: this implementation will first unmarshall the Json document to a JsonElement
s tree and then will retrieve the needed JsonObject
s to create through the delegate the Distance
objects (sorry for the bad code, quickly written).
public class RouteResponseTypeAdapter extends TypeAdapter<RouteResponse> {
private final TypeAdapter<JsonElement> jsonElementTypeAdapter;
private final TypeAdapter<Distance> distanceTypeAdapter;
public RouteResponseTypeAdapter(Gson gson) {
this.jsonElementTypeAdapter = gson.getAdapter(JsonElement.class);
this.distanceTypeAdapter = gson.getAdapter(Distance.class);
}
@Override
public void write(JsonWriter out, RouteResponse value) throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public RouteResponse read(JsonReader jsonReader) throws IOException {
RouteResponse result = new RouteResponse();
List<Distance> distances = new ArrayList<>();
result.setDistances(distances);
if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
JsonObject responseObject = (JsonObject) jsonElementTypeAdapter.read(jsonReader);
JsonArray routes = responseObject.getAsJsonArray("routes");
if (routes != null) {
for (JsonElement element:routes) {
JsonObject route = element.getAsJsonObject();
JsonArray legs = route.getAsJsonArray("legs");
if (legs != null) {
for (JsonElement legElement:legs) {
JsonObject leg = legElement.getAsJsonObject();
JsonElement distanceElement = leg.get("distance");
if (distanceElement != null) {
distances.add(distanceTypeAdapter.fromJsonTree(distanceElement));
}
}
}
}
}
}
return result;
}
}
Finally, you can parse your json document:
String json = "{ routes: [ ....."; // Json document
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new RouteResponseTypeAdapterFactory()).create();
RouteResponse response = gson.fromJson(json, RouteResponse.class);
//response.getDistances() should contain the distances
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With