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?
1 Answer 1
You can parse the complete response easily using Google's Gson library:
class GeoResponse {
List<Result> results;
String status;
static class Result {
List<AddressComponent> address_components;
String formatted_address;
Geometry geometry;
boolean partial_match;
String place_id;
List<String> types;
static class AddressComponent {
String long_name, short_name;
List<String> types;
}
static class Geometry {
Rect bounds;
LatLng location;
String location_type;
Rect viewport;
static class Rect {
LatLng northeast, southwest;
}
static class LatLng {
double lat, lng;
}
}
}
}
...
import com.google.gson.Gson;
class GeoResponseParser {
Gson gson = new Gson();
GeoResponse parse(String responseStr) {
return gson.fromJson(responseStr, GeoResponse.class);
}
}
-
\$\begingroup\$ yea it works, but I wanted to make different structure of object. \$\endgroup\$Edgar– Edgar2016年01月30日 09:01:04 +00:00Commented Jan 30, 2016 at 9:01
-
\$\begingroup\$ @Edgar Then I would recommend letting Gson do the conversion to a Java object and then convert that object to one of the structure you want. \$\endgroup\$Reinstate Monica– Reinstate Monica2016年01月30日 14:35:31 +00:00Commented Jan 30, 2016 at 14:35
JsonParser
? The code would be much shorter. \$\endgroup\$