I am trying to write a parser from JSON data which I get from Google requesting coordinates of a city, which will create my specified object structure. For parsing, I've written a custom TypeAdapter
.
It is my first time working with Gson, so probably my parsing method can be improved. Any suggestions?
JSON I receive:
{
"results" : [
{
"address_components" : [
{
"long_name" : "Los Angeles",
"short_name" : "Los Angeles",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Los Angeles County",
"short_name" : "Los Angeles County",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "California",
"short_name" : "CA",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "Los Angeles, CA, USA",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 34.3373061,
"lng" : -118.1552891
},
"southwest" : {
"lat" : 33.7036917,
"lng" : -118.6681759
}
},
"location" : {
"lat" : 34.0522342,
"lng" : -118.2436849
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 34.3373061,
"lng" : -118.1552891
},
"southwest" : {
"lat" : 33.7036917,
"lng" : -118.6681759
}
}
},
"partial_match" : true,
"place_id" : "ChIJE9on3F3HwoAR9AhGJW_fL-I",
"types" : [ "locality", "political" ]
}
],
"status" : "OK"
}
My POJO: only fields, without setters and getters to save space.
public class GeoLocation {
private String location_longName;
private String location_shortName;
private String country_longName;
private String country_shortName;
private String forrmatedAddress;
private GeoCoordinates locationCordinates;
}
public class GeoCoordinates {
private Point northeastBounds;
private Point southwestBounds;
private Point northeastViewport;
private Point southwestViewport;
private Point location;
}
Custom TypeAdapter
:
public class GeoLocationAdapter extends TypeAdapter<GeoLocation> {
@Override
public void write(JsonWriter jsonWriter, GeoLocation location) throws IOException {
}
@Override
public GeoLocation read(JsonReader jsonReader) throws IOException {
GeoLocation location = parsing(jsonReader);
return location;
}
private GeoLocation parsing(JsonReader reader) throws IOException {
GeoLocation location = new GeoLocation();
GeoCoordinates coordinates = new GeoCoordinates();
location.setLocationCordinates(coordinates);
while (reader.peek() != JsonToken.END_DOCUMENT) {
if (reader.peek() == JsonToken.NAME) {
switch (reader.nextName()) {
case "results":
case "geometry":
break;
case "address_components":
reader.beginArray();
int i = 0;
String longName = null;
String shortName = null;
for (; ; ) {
if (reader.peek() == JsonToken.BEGIN_OBJECT) {
reader.beginObject();
}
if (reader.peek() == JsonToken.NAME) {
switch (reader.nextName()) {
case "long_name":
longName = reader.nextString();
break;
case "short_name":
shortName = reader.nextString();
break;
case "types":
while (reader.peek() != JsonToken.END_OBJECT) {
reader.skipValue();
}
break;
}
}
if (reader.peek() == JsonToken.END_OBJECT) {
if (0 == i++) {
location.setLocation_longName(longName);
location.setLocation_shortName(shortName);
}
reader.endObject();
}
if (reader.peek() == JsonToken.END_ARRAY) {
location.setCountry_longName(longName);
location.setCountry_shortName(shortName);
reader.endArray();
break;
}
}
break;
case "formatted_address":
location.setForrmatedAddress(reader.nextString());
break;
case "bounds":
reader.beginObject();
for (; ; ) {
if (reader.peek() == JsonToken.NAME) {
switch (reader.nextName()) {
case "northeast":
reader.beginObject();
location.getLocationCordinates().setNortheastBounds(parseCoordinates(reader));
reader.endObject();
break;
case "southwest":
reader.beginObject();
location.getLocationCordinates().setSouthwestBounds(parseCoordinates(reader));
reader.endObject();
break;
}
if (reader.peek() == JsonToken.END_OBJECT) {
reader.endObject();
break;
}
}
}
break;
case "location":
reader.beginObject();
location.getLocationCordinates().setLocation(parseCoordinates(reader));
reader.endObject();
break;
case "viewport":
reader.beginObject();
for (; ; ) {
if (reader.peek() == JsonToken.NAME) {
switch (reader.nextName()) {
case "northeast":
reader.beginObject();
location.getLocationCordinates().setNortheastViewport(parseCoordinates(reader));
reader.endObject();
break;
case "southwest":
reader.beginObject();
location.getLocationCordinates().setSouthwestViewport(parseCoordinates(reader));
reader.endObject();
break;
}
if (reader.peek() == JsonToken.END_OBJECT) {
reader.endObject();
break;
}
}
}
break;
default:
reader.skipValue();
break;
}
}
if (reader.peek() == JsonToken.BEGIN_OBJECT) {
reader.beginObject();
}
if (reader.peek() == JsonToken.BEGIN_ARRAY) {
reader.beginArray();
}
if (reader.peek() == JsonToken.END_OBJECT) {
reader.endObject();
}
if (reader.peek() == JsonToken.END_ARRAY) {
reader.endArray();
}
}
return location;
}
private Point parseCoordinates(JsonReader reader) throws IOException {
Double lat = null;
Double lng = null;
while (reader.peek() != JsonToken.END_OBJECT) {
switch (reader.nextName()) {
case "lat":
lat = reader.nextDouble();
break;
case "lng":
lng = reader.nextDouble();
break;
}
}
return new Point(lat, lng);
}
}
Calling:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(GeoLocation.class, new GeoLocationAdapter());
Gson gson = builder.create();
GeoLocation locationObj = gson.fromJson(full, GeoLocation.class);
Please provide any improvements that can be made to code for ac-heaving better readability and performance. Also, can I leave the write method empty if I'm not planning to convert the result object back to JSON?
JsonParser
? The code would be much shorter. \$\endgroup\$