JSON vs JSONP

Why we need JSONP (JSON‘s shortcomings)

JSON is a language designed for lightweight data exchange in an format that is easy for both humans and computers to understand.

Unfortunately, as much as JSON appears to be the best thing since sliced bread as far as web developers are concerned, the technologies used by JavaScript to send and receive JSON messages (XMLHttpRequest, and Microsoft’s family of ActiveXObject‘s) are restricted by the same origin policy which is enforced in all major browsers; i.e. you cannot make a request to a resource using a different protocol, domain or port to which the current page is using.

However, it was discovered that the JSON language we know and love could work on a technology which is not restricted by the same origin policy with only a small amount of changes required. The combination of this technology, along with the adapted form of JSON was branded JSONP.

An introduction to the new technology

You’ll be disappointed to hear that the new-and-exciting technology that is fundamental to JSONP is nothing more than the bog-standard <script> tag.

The full power of the <script> tag is often overlooked, or at the very least, taken for granted:

  1. <script> tags are not restricted by any same origin policy, so can make requests to any domain.

  2. <script> tags can be added programatically, which allows developers to request resources via the <script> tag as and when required:

    var element = document.createElement("script"); // create the element 
    element.src = 'http://somewhere.com/some/resource.js'; // set the target resource
    document.getElementsByTagName("head")[0].appendChild(element); // add the element to the DOM
    
  3. The src attribute of the <script> tag is not restricted to just JavaScript files. Whatever the target, it will be retrieved via the relevant transport protocol (HTTP GET/ HTTPS GET), and the content will be evaluated by the JavaScript engine. If the content is not valid JavaScript, a Parse Error will be thrown.

We can combine these observations to form a two way communication channel between the web page and the remote resource.

  1. Using observations 1 and 2, the client can initiate requests to remote resources. To make the requests useful, it is usual for the target to be server scripted page; such as a PHP file.

        // Example utility function
        function requestViaScript(url) {
          var element = document.createElement("script");
    
          element.src = url;
    
          document.getElementsByTagName("head")[0].appendChild(element);
        }
    
        // Example usage
        requestViaScript('http://example.com/endpoint.php?param1=a&param2=b');
    
  2. Observation 3 states that the resource’s contents is evaluated by the JavaScript engine. Therefore, if the resource returns valid JavaScript which has an effect (e.g. calls a function), the server has a method to respond to the request.

How JSON fits in

As touched upon earlier, JSON is attractive to JavaScript developers because it’s syntax is valid JavaScript; when evaluated, it becomes either an object or an array. However, a JSON response does not have any effect; as the resultant array/object isn’t assigned to anything.

However, we can easily modify the response so instead of returning JSON like so:

{ "foo": [1,2,3,4] }

It is returned like this:

someFunction( { "foo": [1,2,3,4] } );

Which provides the effect we need (someFunction is executed), and JSONP (i.e JSON with padding), is born.

The final piece of the jigsaw

The last question that needs answering is “How does the server know the name of the function to call?”; and the answer is simple.

We pass the name of the function as a parameter in the request.

This parameter is commonly named the “callback” parameter.

requestViaScript('http://example.com/endpoint.php?param1=a&param2=b&callback=foo'); // Server knows to surround the JSON response with foo()

That is all there is to JSONP. Below is some code which provides a complete example of how a simple message exchange is performed on both the client and the server, to help tie any loose ends. That aside, I hope you’ve found this article useful.

Worked Example

In this simple ficticious example, the webpage (client) will sent a number to the server. The server will add VAT to the number, and return the new value.

JavaScript:

function requestViaScript(url) {
  var element = document.createElement("script");

  element.src = url;

  document.getElementsByTagName("head")[0].appendChild(element);
}

function calculateVAT(price) {
  requestViaScript('http://example.com/endpoint.php?price=' + price + '&callback=handleResponse');
}

function handleResponse(response) {
  alert("The price " + response.price + " is " + response.vat + " including VAT");
}

PHP (http://example.com/endpoint.php)

if (isset($_GET['price']) && isset($_GET['callback'])) {
  $response = array();
  $response['price'] = $_GET['price'];
  $response['vat'] = $_GET['price'] * 1.20;

  echo $_GET['callback'] . '(' . json_encode($response) . ')';
}

4 thoughts on “JSON vs JSONP

  1. Nice demonstration.

    I have one question. Is there a way to wrap the JSON after it’s imported (curcumventing the cross-origin limitation) or does the incoming JSON have to already be in JSONP (ie JSON wrapped in a callback) format?

  2. Hi Evan,

    If you’re communicating with a webpage on a different domain (i.e. a request SOP would restrict), the response from the server must already be padded (i.e. in JSONP format). Otherwise you get a response such as { "foo": [1,2,3,4] }, which has no affect (you can’t do anything with it).

    A lot of APIs support the JSONP format, so check the webpage you’re querying doesn’t support this format. If this isn’t an option, you might want to look at a service such as Yahoo Pipes!, which lets you take a data format (in your case JSON) and pipe it into another format (in this case it would be JSONP).

    Hope this helps!

  3. Pingback: Read JSON from URL | PHP Developer Resource

  4. Nice Demonstration which gives clear understanding of JSONP and how to use it.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>