2016.12.05 JSON和JSONP

来源:互联网 发布:电脑图片ps软件 编辑:程序博客网 时间:2024/05/16 14:14

1、JSON和JSONP

JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。


2、JSON的格式

JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。

①JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号”“是定义符;

②大括号{}用来描述一组“不同类型的无序键值对集合”(属性键值对),方括号[]用来描述数组);

③述两种集合中若有多个子项,则通过英文逗号,进行分隔;

④键值对以英文冒号:进行分隔,键名都加上英文双引号”“,以便于不同语言的解析。

⑤JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null这么几个,字符串必须用双引号引起来,其余的都不用。


3、JSON实例:

// 描述一个人var person = {    "Name": "Bob",    "Age": 32,    "Company": "IBM",    "Engineer": true}// 获取这个人的信息var personAge = person.Age;// 描述几个人var members = [    {        "Name": "Bob",        "Age": 32,        "Company": "IBM",        "Engineer": true    },    {        "Name": "John",        "Age": 20,        "Company": "Oracle",        "Engineer": false    },    {        "Name": "Henry",        "Age": 45,        "Company": "Microsoft",        "Engineer": false    }]// 读取其中John的公司名称var johnsCompany = members[1].Company;// 描述一次会议var conference = {    "Conference": "Future Marketing",    "Date": "2012-6-1",    "Address": "Beijing",    "Members":     [        {            "Name": "Bob",            "Age": 32,            "Company": "IBM",            "Engineer": true        },        {            "Name": "John",            "Age": 20,            "Company": "Oracle",            "Engineer": false        },        {            "Name": "Henry",            "Age": 45,            "Company": "Microsoft",            "Engineer": false        }    ]}// 读取参会者Henry是否工程师var henryIsAnEngineer = conference.Members[2].Engineer;

4、JSON对象的两个原生方法:

JSON.stringify()和JSON.parse(),.stringify()方法将JS对象序列化为JSON字符串,会自动将JS函数和原型忽略;JSON.parse()方法解析JSON数据,JSON..parse(a,b)的两个参数a是接受解析的对象,b是含原函数,与替换函数相同,接受两个参数(name,value),返回value;

var boo={a:"value1",    b:"value2"};var c=JSON.stringify(boo);//结果是{"a":"value1,"b":"value2"}alert(c)

JSON.stringify(a,b,c)方法的三个参数,a是需要处理的对象,b是过滤器,c控制缩进字符数(同时换行)。

①b过滤器可以是数组,结果中将只包含数组中列出的属性

var boo={a:"value1",    b:"value2"};var c=JSON.stringify(boo,["a"],"++");//结果是{"a":"value1}alert(c)

②b可以是函数(替换函数),function(name,value){…}//根据key决定如何输出value

var boo={a:"value1",    b:"value2",    c:["value3","value4"],    d:"value5"};var c=JSON.stringify(boo,function(name,value){    switch (key){        case "a":            return "加油";        case "b":            return undefined;//相当于删除该项        case "c":            return value.join("+++");        default :            return value;//确保其他值可以出现    }},"++");alert(c)

输出结果:

这里写图片描述

③c是控制字符缩进数,数字代表空格数,用字符串则使用该字符串进行缩进;

### 4、JSONP:
①一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

②不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如


5、JSONP实现跨域(JS原生方法):

①我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

alert('我是远程文件');

本地服务器localserver.com下有个jsonp.html页面代码如下:

<!DOCTYPE html><html><head>    <title></title>    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script></head><body></body></html>

毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。
②现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。jsonp.html页面代码如下:

<!DOCTYPE html><html><head>    <title></title>    <script type="text/javascript">        var localHandler =function(data){            alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:'+ data.result);        };    </script>    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script></head><body></body></html>

remote.js文件代码如下:

localHandler({"result":"我是远程js带来的数据"});

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同,我们接着往下看。

③聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。内部看jsonp.html页面的代码:

<!DOCTYPE html><html><head>    <title></title>    <script type="text/javascript">        // 得到航班信息查询结果后的回调函数        var flightHandler =function(data){            alert('你查询的航班结果是:票价 '+ data.price +' 元,'+'余票 '+ data.tickets +' 张。');        };        // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)        var url ="http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";        // 创建script标签,设置其属性        var script = document.createElement('script');        script.setAttribute('src', url);        // 把script标签加入head,此时调用开始        document.getElementsByTagName('head')[0].appendChild(script);    </script></head><body></body></html>

这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分。我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

flightHandler({    "code": "CA1998",    "price": 1780,    "tickets": 5});

我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成


6、JSONP的jQuery方法:

下面是jQuery使用jsonp的代码(使用锋利的jQuery中的flickr的例子,特地科学上网验证):通过.getJSON().ajax实现,但是都需要服务器端的支持:

$("#send").click(function() {    $.ajax({        type: "get",        async: false,        url: "http://api.flickr.com/services/feeds/photos_public.gne?tags=car&tagmode=any&format=json&jsoncallback=?",        dataType: "jsonp",        success : function(data) {            $.each(data.items, function (i, item) {                $("<img class='para'/> ").attr("src", item.media.m).appendTo("#resText");                if (i == 3) {                    return false;                }            });        },        error: function (json) {            alert("ccf")        }    })});//jQuery的$.getJSON()方法使用JSONP形式跨域$(function(){    $("#send").click(function(){        $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=car&tagmode=any&format=json&jsoncallback=?",            function(data) {                $.each(data.items, function (i, item) {                    $("<img class='para'/> ").attr("src", item.media.m).appendTo("#resText");                    if (i == 3) {                        return false;                    }                })            })    })});

7、JSONP的问题:

①只支持GET,不能很好的支持POST;

②对服务器段有限制

0 0