Getting started with JSON-P
I have during my college days used XMLHttpRequest object and its equivalent in Microsoft world to make Ajax calls and those Ajax calls were to the URL within the same domain. But with the advent of Webservices and whole lot of mashups being developed, Ajax calls are not restricted to same domain but the cut acorss different domains. When this cutting across domain boundaries happens making Ajax calls using XMLHttpRequest fails due to security enforcements implemened by the browsers. That’s when the idea of JSON-P i.e JSON with Padding came up.
In this post I will quote from different sources about JSONP and then go ahead and implement example which invokes Stackoverflow API to retrieve the unanswered questions tagged ‘jsonp’
What is JSONP?
I am not going to restate its definition, instead quote its definition from different sources as given below:
From Head First HTML5:
JSONP is a way to retrieve JSON objects by using the
script
tag. It’s also a way of retrieving data (again, in the form of JSON objects) that avoids the same-origin security issues we saw with XMLHttpRequest. JSONP is JSON data wrapped in JavaScript; typically, a function call.
From http://json-p.org/
One such mechanism which can request content cross-domain is the
script
tag. In December 2005, Bob Ippolito formally proposed JSONP (later dubbed JSON-P, or JSON-with-padding) as a way to leverage this property ofscript
tags to be able to request data in the JSON format across domains. JSON-P works by making ascript
element (either in HTML markup or inserted into the DOM via JavaScript), which requests to a remote data service location. The response (the loaded “JavaScript” content) is the name of a function pre-defined on the requesting web page, with the parameter being passed to it being the JSON data being requested. When the script executes, the function is called and passed the JSON data, allowing the requesting page to receive and process the data.
From Wikipedia: http://en.wikipedia.org/wiki/JSONP
JSONP or “JSON with padding” is a communication technique used in JavaScript programs which run in Web browsers. It provides a method to request data from a server in a different domain, something prohibited by typical web browsers because of the same origin policy.
Summarising, JSONP is a communication technique to retrieve data from some URL and then leveraging the script
tag to establish the communication and JavaScript to update the HTML.
There have been a lot of concerns about how secure using JSONP is, but I dont want to get into those discussions as that is not the main motive of this post.
Now going forward, let me show JSONP in action using a simple example.
Simple example for JSONP
For the simple example I will make use of some resources from chapter on JSONP in Head First HTML5 book. I am going to make a JSONP call to a Javascript resource which in turns invokes the callback function declared in my Javascript source.
Lets look at the HTML source:
<html> <head> <title></title> <meta charset='UTF-8'> <script src='simple.js'></script> </head> <body> <h1>JSONP Simple Demo</h1> <!-- we will update the data here --> <div id='jsonp'></div> </body> </html>
The interesting thing happens in the JavaScript code.
//simple.js window.onload = function(){ //Get the head element. var head = document.getElementsByTagName('head')[0]; //url for the javascript resource for JSONP call. var url = 'http://wickedlysmart.com/hfhtml5/chapter6/dog3.js'; //Appending the script tag to the head element. //This triggers a JSONP call to get the data. var scriptTag = document.createElement('script'); scriptTag.setAttribute('src',url); head.appendChild(scriptTag); } //Method invoked by JSONP function animalSays(animal){ var div = document.getElementById('jsonp'); div.innerHTML = animal.type +' says '+ animal.sound; }
The “http://wickedlysmart.com/hfhtml5/chapter6/dog3.js” contains:
var animal = { 'type': 'dog', 'sound': 'woof' }; animalSays(animal);
The above javascript code:
1. creates a JSON object
2. invokes the callback by pasing the JSON object.
Now the question is, where is the animalSays
method declared? If you have carefully looked at simple.js you can see that the method animalSays
has been declared. When the javascript in above URL is requested using JSONP technique by dynamically adding the script
, the javascript is executed in the browser which contains the definition of the animalSays
method.
The animalSays
method retrieves the JSON object and then populates the HTML with the data in the JSON object.
Lets look at a more better example.
Accessing Stackoverflow API using JSONP
Details of the Stackoverflow API for unanswered questions can be found here. The URL for accessing unanswered questions tagged ‘jsonp’ is: https://api.stackexchange.com/2.1/questions/unanswered?order=desc&sort=activity&tagged=jsonp&site=stackoverflow
The above URL returns some JSON data, but how does it help in making use of JSONP? One can append another parameter to the above URL called “callback” which will take the name of the Javascript method which will be invoked once the URL is loaded by the script
tag.
Lets take a look at the HTML code:
//sflow.html <!DOCTYPE html> <html> <head> <title></title> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <script src='sflow.js'></script> </head> <body> <div>Unanswered questions tagged 'jsonp'</div> <!-- placeholder for updating the questions --> <div id='questions'> </div> </body> </html>
The Javascript code has 2 parts:
- Part-1: Loading the URL which contains the data and the function invocation.
window.onload = function() { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); var url = 'https://api.stackexchange.com/2.1/questions/unanswered?' + 'order=desc' + '&sort=activity' + '&tagged=jsonp' + '&site=stackoverflow' + '&callback=listUnansweredQuestions'; //The URL is loaded by including it in the script tag and adding to the DOM. script.setAttribute('src', url); head.appendChild(script); }
- Part-2: Defining the callback which gets the data and then updates the HTML
function listUnansweredQuestions(questions) { var div = document.getElementById('questions'); var ul = document.createElement('ul'); div.appendChild(ul); for (var i = 0; i < questions.items.length; i++) { var question = questions.items[i]; var li = document.createElement('li'); li.innerHTML = '<a href='+question.link+'>'+question.title+'</a>'; ul.appendChild(li); } }
The complete Javascript code would be:
//sflow.js window.onload = function() { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); var url = 'https://api.stackexchange.com/2.1/questions/unanswered?' + 'order=desc' + '&sort=activity' + '&tagged=jsonp' + '&site=stackoverflow' + '&callback=listUnansweredQuestions'; script.setAttribute('src', url); head.appendChild(script); } function listUnansweredQuestions(questions) { var div = document.getElementById('questions'); var ul = document.createElement('ul'); div.appendChild(ul); for (var i = 0; i < questions.items.length; i++) { var question = questions.items[i]; var li = document.createElement('li'); li.innerHTML = '<a href='+question.link+'>'+question.title+'</a>'; ul.appendChild(li); } }
The output for the above HTML and Javascript would be:
If you have any issues in running any of the sample code shown in the post above, please get in touch via the comments below.
Reference: | Getting started with JSON-P from our WCG partner Mohamed Sanaulla at the Experiences Unlimited blog. |