JSON和JSONP
与XML相比,JSON是一个轻量级的数据交换格式。JSON对于JavaScript开发人员充满魅力的原因在于JSON本身就是Javascript中的对象。
例如一个ticker对象
var ticker = {symbol:'IBM',price:100}
而JSON串就是 {symbol:'IBM',price:100}
这样我们就可以在函数的参数中传递JSON数据。我们很容易掌握在函数中使用动态的JSON参数数据,但是我们的目的并不是这个。
通过使我们的函数能够加载动态的JSON数据,我们就能够处理动态的数据,这项技术叫做 Dynamic Javascript Insertion。
我们看下面的例子:
index.html中
上面的代码通过动态加入Javascript代码,来执行函数加载数据。
~~~动态创建<script>元素,引入并执行js文件,js文件中包含json数据,并将json数据作为参数传入主页面的全局函数 <script>src属性引入脚本不受同源策略许限制
正如之前提到过的,同源策略对于动态插入的代码不适用。也就是你可以从不同的域中加载代码,来执行在他们代码中的JSON数据。~~~从不同的域中加载数据,回调本页面的全局函数
这就是JSONP(JSON with Padding)。注意,使用这种方法时,你必须在页面中定义回调函数,就像上例中的showPrice一样。
我们通常所说的JSONP服务(远程JSON服务),实际上就是一种扩展的支持在用户定义函数中包含返回数据的能力。这种方法依赖于必须接受一个回调函数的名字作为参数。
然后执行这个函数,处理JSON数据,并显示在客户页面上。
JQuery的JSONP支持
从JQery 1.2以后,就开始支持JSONP的调用。在另外的一个域名中指定好回调函数名称,你就可以用下面的形式来就加载JSON数据。
url?callback=?
示例:
jquery会在window对象中加载一个全局的函数,当代码插入时函数执行,执行完毕后就会被移除。同时jquery还对非跨域的请求进行了优化,如果这个请求是在同一个域名下那么他就会像正常的Ajax请求一样工作。
上例中我们在动态插入到页面的代码中使用了静态的json数据,虽然完成了依次JSONP返回,但仍不是JSONP服务,因为不支持在URL中定义回调函数名称。下面是一个将其变成JSONP服务的一个方法
服务器端使用PHP。
首先我们来定义接口的规范,就像这样:http://www.mydomain.com/jsonp/ticker?symbol=IBM&callback=showPrice
symbol是请求条件,callback是回调函数名称。
在页面文件中,我们使用JQuery的支持:
在suggest.php中
~~~jQuery检测目标url,若非同源,则jsonp工作方式: 在window下创建全局函数如(window.abcd=function(data){alert("Symbol:" + data.symbol + ", Price:" + data.price}), 创建script元素 src=url(http://www.mydomain.com/....php?symbol=IBM&callback=abcd); php页面返回 abcd({symbol:'IBM', price:120}); window.abcd = null
~~~如果为url为同源,则普通$.get(url, callback)的方式工作
再举个.NET webservice 的例子
客户端
服务器端
现在,如果我们想制作一些mashup,或者将第三方的资源整合到一个页面中,我们就很容易想到JSONP的解决方法了。
注意:
JSONP是一个非常强大的构建mashup的方法,可是不是一个解决跨域访问问题的万能药。它也有一些缺点:
第一也是最重要的:JSONP不提供错误处理。如果动态插入的代码正常运行,你可以得到返回,但是如果失败了,那么什么都不会发生。你无法获得一个404的错误,也不能取消这个请求。
另外一个重要的缺点是如果使用了不信任的服务会造成很大的安全隐患。