XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

JSON and the Dynamic Script Tag: Easy, XML-less Web Services for JavaScript

December 21, 2005

Making requests to third-party web services from an AJAX application is a pain, but new web services that offer the option of returning JSON (JavaScript Object Notation) instead of XML can provide significant relief. In fact, if you make web services requests using the dynamic script tag approach -- and the web service lets you specify a JavaScript callback function -- you can have unfettered access to the web service in a seamless, cross-domain, cross-browser fashion.

Here's what you need to try out this dynamic script tag request:

  1. My JSONscriptRequest class
  2. Access to a web service that returns JSON and lets you specify a callback function

To create my class, I distilled a lot of existing information, and then adapted it to fit no. 2 above. Until recently, finding a web service that returns JSON and lets you specify a callback function was, well, darn near impossible unless you wrote one yourself. Fortunately, Yahoo recently has offered the option on many of their REST-ish web services. Notably, their many search web services, and their geocoding, map image, and traffic web services, now can return JSON wrapped in a callback function.

The KISS Factor

Compared to using the XMLHttpRequest object and a proxy, this stuff is easy. The JSONscriptRequest class does the messy work of creating the script tag dynamically which makes the actual web service request. For a quick example, I'll do some geocoding, turning a zip code -- in this case zip code 94107 -- into a latitude/longitude pair, using Yahoo's Geocoding Web Service.

<html>
<body>
// Include the JSONscriptRequest class
<script type="text/javascript" src="jsr_class.js"> </script>
<script type="text/javascript">

  // Define the callback function
  function getGeo(jsonData) {     
     alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude + ' Longitude = ' + jsonData.ResultSet.Result[0].Longitude);
     bObj.removeScriptTag(); 
  }

// The web service call
var req  = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&output=json&callback=getGeo&location=94107'; 
// Create a new request object
bObj = new JSONscriptRequest(req); 
// Build the dynamic script tag
bObj.buildScriptTag(); 
// Add the script tag to the page
bObj.addScriptTag();
</script>

</body>
</html>

Running this application makes a request to Yahoo's Geocode web service and yields the following alert box which displays the latitude and longitude of the zip code 94107.

alert box
Figure 1. Alert box

The web service request -- the req variable in the script above -- specifies that the web service should return JSON-encoded data (output=json) and that the data should be wrapped in a callback function named getGeo (callback=getGeo). You can cut and paste that URL into your browser to see the output of the web service. The output looks like this (or click here):


getGeo({"ResultSet":{"Result":[{"precision":"zip","Latitude":"37.7668","Longitude":"-122.3959","Address":"","City":"SAN FRANCISCO","State":"CA","Zip":"94107","Country":"US"}]}});

That's a valid JavaScript statement, so it can be the target of a script tag that returns JavaScript (raw JSON data, without the callback function, is not a valid JavaScript statement, so it will fail to load if it is the target of a script tag). For comparison, look at the XML version of this call here.

The buildScriptTag method of the JSONscriptRequest object builds a script tag that looks like this:


<script src="getGeo({"ResultSet":{"Result":[{"precision":"zip","Latitude":"37.7668","Longitude":"-122.3959","Address":"","City":"SAN FRANCISCO","State":"CA","Zip":"94107","Country":"US"}]}});" type="text/javascript">

To actually execute the web service request, the script tag has to be added to the page. The addScriptTag method attaches the script tag to the HTML page which is already loaded in your browser window. That action causes the getGeo function to be called and the JSON-encoded data to be passed to the getGeo function. Now comes the magic part of the script -- it's a side effect of using JSON-encoded data instead of XML. When a string of JSON-encoded data is used as an argument to a JavaScript function, the JavaScript interpreter automatically turns the JSON into a JavaScript object. Essentially, the parsing step is done automatically and you can reference the data immediately:


alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude + ' Longitude = ' + jsonData.ResultSet.Result[0].Longitude);

Pages: 1, 2

Next Pagearrow