十四、JSON、JSONP、jQuery等

一、JSON(JavaScript Object Notation)是一种在浏览器和服务器之间交换数据的格式,可用于传递对象(key-value对,数组或其他对象)。JSON可以在JavaScript里传递到eval()方法中使用,也能使用Ajax方法来传递(例如httpWebRequest)。

JSON很像XML,但比XML要轻量级,都可以自描述,通过层级的形式,能被多种语言解析和使用。

格式:最完整格式{root:[{attr1:value1},...,{attrn:valuen}]}

注:{}表示一个容器,如外层的{}表示json对象,里层的{}表示key-value对对象。[]表示数组。名称和值用冒号隔开。数组元素之间通过逗号隔开。

如何使用JSON:

1.JSONObject实现JavaBean和json对象之间的相互转换。

javaBean-->json对象          JSONObject     jsonObject = JSONObject.fromObject(javaBean);

json对象-->javaBean          Object                javaBean   = JSONObject.toBean(jsonObject);

2.Jsonarray实现java集合与json对象之间的相互转换。

java集合-->json对象           JSONArray         jsonArray   = JSONArray.fromObject(java集合);

json对象-->java数组           Object                 array           = JSONArray.toArray(jsonArray);

json对象-->List                    Object                 list               = JSONArray.toList(jsonArray);


Json依赖JavaScript,因为json是javascript对象的字符串表示。可以将json数据作为调用的javascript函数的参数传递。示例如下:

<script type="text/javascript">
function functionName(data) {
    alert("attr1 : " + data.attr1 + ", attr2: " + data.attr2);
}
</script>
<script type="text/javascript">
functionName({attr1 : value1, attr2: value2});
</script>
上面是将静态json数据作为参数调用 JavaScript 函数。不过通过在函数调用中动态包装json数据可以用动态数据调用函数,这是一种动态 JavaScript 插入的技术。
要查看其效果,将上面
showPrice({attr1 : value1, attr2: value2});
一行放入如下的 dynamicway.js 的独立 JavaScript 文件中。
<script type="text/javascript">
function functionName(data) {
    alert("attr1 : " + data.attr1 + ", attr2: " + data.attr2);
}
var url = “dynamicway.js”; // URL of the external script
// this shows dynamic script insertion
var script = document.createElement('script');
script.setAttribute('src', url);

// load the script
document.getElementsByTagName('head')[0].appendChild(script); 
</script>
动态插入的 JavaScript 代码位于 dynamicway.js 文件中,它将真正的json数据作为参数调用 functionName()函数。
同源策略不阻止将动态脚本元素插入文档中。也就是说,可以动态插入来自不同域的 JavaScript,并且这些域都携带 JSON 数据。注意,为了完成该操作,Web 页面必须在插入时具有已经定义好的回调函数,也就是我们例子中的 functionName()


 

二、JSONP(JSON with Padding --打包在函数调用中的 JSON 数据)

        所谓的 JSONP (JSON with Padding)服务(或 Remote JSON Service)是一种带有附加功能的 Web 服务,该功能支持在特定的函数调用中打包返回的 JSON 数据。这种方法依赖于接受回调函数名作为请求参数的远程服务。然后该服务生成对该函数的调用,将 JSON 数据作为参数传递,在到达客户端时将其插入 Web 页面并开始执行。

        JSONP 允许在服务器端集成Script tags返回给客户端,通过JavaScript callback的形式实现跨域访问。由于JSON是含有简单括号结构的纯文本,因此很多通道都可以交换JSON数据。因为同源策略的限制,我们不能在与外部服务器进行通信的时候使用XMLHttpRequest,而JSONP是一种可以通过使用JSON与<script>标记相结合的方式来绕过同源策略的方法,所以可以从服务器端直接返回可执行的JavaScript函数调用或者JavaScript对象。

如何使用JSONP

         在上面的例子中,使用了静态文件(dynamicway.js)将 JavaScript 动态插入到 Web 页面中。尽管返回了 JSONP 回复,但它不允许您在 URL 中定义回调函数名,这还不是真正的JSONP 服务。因此,如何才能将其转换为真正的 JSONP 服务呢?

 

首先,假设在所请求的 URL 中接受了一个名为 callback 的参数。(参数名不重要,但是客户端和服务器必须保持名称)。假设向服务发送的请求是这样的:

http://www.yourdomain.com/jsonp/functionname?attr1=value1&callback=value2
在这种情况下,在这种情况下,symbol 是表示请求 functionname attr1的请求参数,而 callback 是 Web 应用程序的回调函数的名称。
使用如下代码可以通过 jQuery 的 JSONP 支持调用该服务:
jQuery.getJSON("http://www.yourdomain.com/jsonp/functionname?attr1=value1&callback=?", 
function(data) {
    alert("attr1 : " + data.attr1 + ", attr2: " + data.attr2);
});
我们使用 ? 作为回调函数名,而非真实的函数名。因为 jQuery 会用生成的函数名替换 ?
下面用Java servlet实现jsonp服务:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	String jsonData = getDataAsJson(req.getParameter("attr2"));
	String output = req.getParameter("callback") + "(" + jsonData + ");";

	resp.setContentType("text/javascript");
          
	PrintWriter out = resp.getWriter();
	out.println(output);
}
 

 

三、jQuery对JSONP的支持

        jQuery拥有对JSONP回调的本地支持。如果指定了JSONP回调,就可以加载位于另一个域的JSON数据。jQuery也能优化非跨域调用,如果向同一个域发出请求,jQuery就将其转化为普通Ajax请求。

        回调的语法为url&callback=?                          jQuery会自动将?替换为要调用的生成函数名。示例如下:

jQuery.getJSON(url+"&callback=?",function(data){

      alert("attr1:"+data.value1+",attr2:"+data.value2);

});

jQuery 将一个全局函数附加到插入脚本时需要调用的对象。

另外,jQuery 也能优化非跨域调用。如果向同一个域发出请求,jQuery 就将其转化为普通 Ajax 请求。

 

 

注:同源策略限制

同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。

克服该限制的一个相对简单的方法是让 Web 页面向它源自的 Web 服务器请求数据,并且让 Web 服务器像代理一样将请求转发给真正的第三方服务器。尽管该技术获得了普遍使用,但它是不可伸缩的。

另一种方式是使用框架要素在当前 Web 页面中创建新区域,并且使用 GET 请求获取任何第三方资源。不过,获取资源后,框架中的内容会受到同源策略的限制。

克服该限制更理想方法是在 Web 页面中插入动态脚本元素,该页面源指向其他域中的服务URL 并且在自身脚本中获取数据。脚本加载时它开始执行。该方法是可行的,因为同源策略不阻止动态脚本插入,并且将脚本看作是从提供 Web 页面的域上加载的。但如果该脚本尝试从另一个域上加载文档,就不会成功。幸运的是,通过添加 JavaScript Object Notation (JSON) 可以改进该技术

你可能感兴趣的:(十四、JSON、JSONP、jQuery等)