Current Articles | RSS Feed
In the first part of this series, we studied how to implement and use a server-side proxy to contact a remote service, and how to use the Google Web Toolkit (GWT) to process the XML results from the Google Geocoding API. For many applications, however, JSON (JavaScript Object Notation) is an even better fit than XML for GWT, since it can be easily processed with JavaScript. Let's see how to use this alternative format, and, by the way, discover how to do so without any server-side proxies by means of JSON with Padding (JSONP), an interesting extension of the JSON concept.
Since version 2.0, GWT has provided several classes and methods that make it simple to process JSON. First we'll build on the code we created in the first article in this series, using the same proxy, then we'll move over to JSONP, which will let us directly access the service from our client application.
http://maps.googleapis.com/maps/geo?output=json&q=10901%20W%20120th%20Ave,Broomfield,CO&sensor=false
{ "results" : [ { "address_components" : [ { "long_name" : "10901", "short_name" : "10901", "types" : [ "street_number" ] }, { "long_name" : "W 120th Ave", "short_name" : "W 120th Ave", "types" : [ "route" ] }, { "long_name" : "Broomfield", "short_name" : "Broomfield", "types" : [ "locality", "political" ] }, ...several snipped lines... { "long_name" : "80021", "short_name" : "80021", "types" : [ "postal_code" ] } ], "formatted_address" : "10901 W 120th Ave, Broomfield, CO 80021, USA", "geometry" : { "location" : { "lat" : 39.9159880, "lng" : -105.1178850 }, "location_type" : "ROOFTOP", "viewport" : { ...several snipped lines... } }, "types" : [ "street_address" ] } ], "status" : "OK"}
private final ServerProxyAsync serverProxy= GWT.create(ServerProxy.class);getJsonFromServerButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { serverProxy.getFromRemoteServer( "http://maps.googleapis.com/maps/api/geocode/json?address=" + URL.encode(addressField.getText()) + "&sensor=false", new AsyncCallback<String>() { @Override public void onFailure(Throwable caught) { Window.alert("Failure getting JSON through proxy"); } @Override public void onSuccess(String result) { processJson(result); } }); }});
processJson(…)
JsonUtils.unsafeEval(...)
eval(...)
public void processJson(final String json) { final GeoDataV3 gd3= JsonUtils.unsafeEval(json); latitudeField.setText("" + gd3.getLatitude()); longitudeField.setText("" + gd3.getLongitude()); String detailedAddress= ""; for (int i= 0; i < gd3.getAddressComponentsLength(); i++) { String separator= ""; for (int j= 0; j < gd3.getAddressComponentTypeLength(i); j++) { detailedAddress= detailedAddress + separator + gd3.getAddressComponentType(i, j); separator= ", "; } detailedAddress= detailedAddress + ": " + gd3.getAddressPartsLongName(i) + ""; } fullAddressField.setText(detailedAddress);}
GeoDataV3
getLatitude(…)
getLongitude(…)
getAddressComponentsLength(…)
AddressComponents
getAddressComponentType(…)
JavaScriptObject
native
package com.google.gwt.kereki.xmlJsonTest.client;import com.google.gwt.core.client.JavaScriptObject;public class GeoDataV3 extends JavaScriptObject { protected GeoDataV3() { } public final native String getAddressPartsLongName(final int i) /*-{ return this.results[0].address_components[i].long_name; }-*/; public final native int getAddressComponentsLength() /*-{ return this.results[0].address_components.length; }-*/; public final native String getAddressComponentType(final int i, final int j) /*-{ return this.results[0].address_components[i].types[j]; }-*/; public final native int getAddressComponentTypeLength(final int i) /*-{ return this.results[0].address_components[i].types.length; }-*/; public final native float getLatitude() /*-{ return this.results[0].geometry.location.lat; }-*/; public final native float getLongitude() /*-{ return this.results[0].geometry.location.lng; }-*/;}
http://maps.googleapis.com/maps/geo?output=json&q=10901%20W%20120th%20Ave,Broomfield,CO&sensor=false&callback=yourcode
yourcode(…)
yourcode && yourcode({ "name": "10901 W 120th Ave,Broomfield,CO", "Status": { "code": 200, "request": "geocode" }, "Placemark": [ { "id": "p1", "address": "10901 W 120th Ave, Broomfield, CO 80021, USA", "AddressDetails": { "Accuracy" : 8, "Country" : { "AdministrativeArea" : { "AdministrativeAreaName" : "CO", "Locality" : { "LocalityName" : "Broomfield", "PostalCode" : { "PostalCodeNumber" : "80021" }, "Thoroughfare" : { "ThoroughfareName" : "10901 W 120th Ave" } } }, "CountryName" : "USA", "CountryNameCode" : "US" } }, "ExtendedData": { "LatLonBox": { ...some lines snipped out... } }, "Point": { "coordinates": [ -105.1178850, 39.9159880, 0 ] } }]})
JsonpRequestBuilder
callback=
setCallbackParam(…)
getJsonDirectlyButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { final JsonpRequestBuilder jsonprb= new JsonpRequestBuilder(); jsonprb.requestObject( "http://maps.googleapis.com/maps/geo?output=json&q=" + URL.encode(addressField.getText()) + "&sensor=false", new AsyncCallback() { @Override public void onFailure(Throwable caught) { Window .alert("Failure getting JSONP directly from remote server"); } @Override public void onSuccess(GeoDataV2 result) { processJsonp(result); } }); }});
GeoDataV2
package com.google.gwt.kereki.xmlJsonTest.client;import com.google.gwt.core.client.JavaScriptObject;public class GeoDataV2 extends JavaScriptObject { protected GeoDataV2() { } public final native String getAddress() /*-{ return this.Placemark[0].address; }-*/; public final native String getLocality() /*-{ return this.Placemark[0].AddressDetails.Country.AdministrativeArea.Locality.LocalityName; }-*/; public final native String getPostalCode() /*-{ return this.Placemark[0].AddressDetails.Country.AdministrativeArea.Locality.PostalCode.PostalCodeNumber; }-*/; public final native float getLatitude() /*-{ return this.Placemark[0].Point.coordinates[1]; }-*/; public final native float getLongitude() /*-{ return this.Placemark[0].Point.coordinates[0]; }-*/;}
public void processJsonp(final GeoDataV2 gd2) { fullAddressField.setText(gd2.getAddress() + "Locality:" + gd2.getLocality() + "Postal Code:" + gd2.getPostalCode()); latitudeField.setText("" + gd2.getLatitude()); longitudeField.setText("" + gd2.getLongitude());}
Allowed tags: <a> link, <b> bold, <i> italics