JSON / JSONP and Same Origin policy issue
First of all, what the JSON is? It is very, very simple! JSON acronym of a JavaScript Object Notation. It is a data interchange format, analog of XML. It became very popular because of AJAX applications, which receive a data from web services called from a javascript. Web services typically use XML as format of exchanging data, that works great because of SOAP standard and so on.. But in javascript client application you had to put additional effort of parsing XML data, and create an XML to post to web service. JSON simplifies it, because it is native to javascript.
JSON is a serialization of javascript object to string. It based on javascript basic types as Number, String, Boolean, Array, Object and null and looks like that:
{
"id": 1023,
"description": "new assigment",
"data": {
"size": 117,
"url": "/local/data/jhsr2kk"
}
}
* This source code was highlighted with Source Code Highlighter.
As you receive such string from web service (for instance) you can just evaluate it (with eval() function) and use as javascipt object. (I have to mention that direct using of eval() is not recommended way since security issues, all modern browsers have built-in JSON parsers and you can use that. Best way is to use a libraries, like jQuery or Prototype and hides such details from you).
JSON exchanging of data works great as soon as your application and data source service are in one domain. As you want to receive some data outside of your domain, it simply won’t work (it actually works, with IE but it gives security notification and does not work in Chrome at all). This because of Same origin policy, security concept that disallow such operations. So, as you considered to do something like,
$.getJSON("http://external.com/json", function(data) { });
* This source code was highlighted with Source Code Highlighter.
you will not get any result. There are a different approaches of workaround of same policy origin (please check nice article on that), but as you know that web service supports JSON, JSONP comes to help.
JSONP is a JSON with padding (or it also called JSON with prefix). With JSONP you are specifying URL and callback function, like http://external.com/json?callback=f. This must be put into script tag.
<script type="text/javascript" src="http://external.com/json?callback=f">
function f(data) {
}
</script>
* This source code was highlighted with Source Code Highlighter.
It is allowed and works perfectly fine.
But what if you need a dynamic calls? It is also not a problem, it is possible to create script tag dynamically and attach it to DOM. A nice way of doing that. I’ve seen in github-api project. Original code is from here, I just removed some details and made it more reusable.
(function (globals) {
var json = {
__jsonp_callbacks: {},
call: function (url, callback, context) {
var id = +new Date;
var script = document.createElement("script");
json.__jsonp_callbacks[id] = function () {
delete json.__jsonp_callbacks[id];
callback.apply(context, arguments);
};
var prefix = "?";
if (url.indexOf("?") >= 0)
prefix = "&";
url += prefix + "callback=" + encodeURIComponent("json.__jsonp_callbacks[" + id + "]");
script.setAttribute("src", url);
document.getElementsByTagName('head')[0].appendChild(script);
}
}
globals.json = json;
})(window);
* This source code was highlighted with Source Code Highlighter.
Example of usage:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test page</title>
<script type="text/javascript" src="json.js"></script>
</head>
<body>
<script type="text/javascript">
json.call("http://ws.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de", function (data) {
var d = data;
}
);
</script>
</body>
</html>
* This source code was highlighted with Source Code Highlighter.
This code very useful for small “depends-on-nothing” applications. Of cause jQuery has its own support of JSONP, so as soon as you already using jQuery you should consider $.getJSON for your needs.
First of all, what the JSON is? It is very, very simple! JSON acronym of a JavaScript Object Notation. It is a data interchange format, analog of XML. It became very popular because of AJAX applications, which receive a data from web services called from a javascript. Web services typically use XML as format of exchanging data, that works great because of SOAP standard and so on.. But in javascript client application you had to put additional effort of parsing XML data, and create an XML to post to web service. JSON simplifies it, because it is native to javascript.
JSON is a serialization of javascript object to string. It based on javascript basic types as Number, String, Boolean, Array, Object and null and looks like that:
{
"id": 1023,
"description": "new assigment",
"data": {
"size": 117,
"url": "/local/data/jhsr2kk"
}
}
* This source code was highlighted with Source Code Highlighter.
As you receive such string from web service (for instance) you can just evaluate it (with eval() function) and use as javascipt object. (I have to mention that direct using of eval() is not recommended way since security issues, all modern browsers have built-in JSON parsers and you can use that. Best way is to use a libraries, like jQuery or Prototype and hides such details from you).
JSON exchanging of data works great as soon as your application and data source service are in one domain. As you want to receive some data outside of your domain, it simply won’t work (it actually works, with IE but it gives security notification and does not work in Chrome at all). This because of Same origin policy, security concept that disallow such operations. So, as you considered to do something like,
$.getJSON("http://external.com/json", function(data) { });
* This source code was highlighted with Source Code Highlighter.
you will not get any result. There are a different approaches of workaround of same policy origin (please check nice article on that), but as you know that web service supports JSON, JSONP comes to help.
JSONP is a JSON with padding (or it also called JSON with prefix). With JSONP you are specifying URL and callback function, like http://external.com/json?callback=f. This must be put into script tag.
<script type="text/javascript" src="http://external.com/json?callback=f">
function f(data) {
}
</script>
* This source code was highlighted with Source Code Highlighter.
It is allowed and works perfectly fine.
But what if you need a dynamic calls? It is also not a problem, it is possible to create script tag dynamically and attach it to DOM. A nice way of doing that. I’ve seen in github-api project. Original code is from here, I just removed some details and made it more reusable.
(function (globals) {
var json = {
__jsonp_callbacks: {},
call: function (url, callback, context) {
var id = +new Date;
var script = document.createElement("script");
json.__jsonp_callbacks[id] = function () {
delete json.__jsonp_callbacks[id];
callback.apply(context, arguments);
};
var prefix = "?";
if (url.indexOf("?") >= 0)
prefix = "&";
url += prefix + "callback=" + encodeURIComponent("json.__jsonp_callbacks[" + id + "]");
script.setAttribute("src", url);
document.getElementsByTagName('head')[0].appendChild(script);
}
}
globals.json = json;
})(window);
* This source code was highlighted with Source Code Highlighter.
Example of usage:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test page</title>
<script type="text/javascript" src="json.js"></script>
</head>
<body>
<script type="text/javascript">
json.call("http://ws.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de", function (data) {
var d = data;
}
);
</script>
</body>
</html>
* This source code was highlighted with Source Code Highlighter.
This code very useful for small “depends-on-nothing” applications. Of cause jQuery has its own support of JSONP, so as soon as you already using jQuery you should consider $.getJSON for your needs.