JSON與JSONP的區(qū)別【轉】

本文轉自模闲,博客園查剖,昵稱:[隨它去吧]贯被,

http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

非常感謝。

前言:

說到AJAX就會不可避免的面臨兩個問題咳胃,第一個是AJAX以何種格式來交換數(shù)據植康?第二個是跨域的需求如何解決?這兩個問題目前都有不同的解決方案拙绊,比如數(shù)據可以用自定義字符串或者用XML來描述向图,跨域可以通過服務器端代理來解決泳秀。

但到目前為止最被推崇或者說首選的方案還是用JSON來傳數(shù)據标沪,靠JSONP來跨域榄攀。而這就是本文將要講述的內容。

JSON和JSONP雖然只有一個字母的差別金句,但其實他們根本不是一回事兒:JSON是一種數(shù)據交換格式檩赢,而JSONP是一種依靠開發(fā)人員的聰明才智創(chuàng)造出的一種非官方跨域數(shù)據交互協(xié)議。我們拿最近比較火的諜戰(zhàn)片來打個比方违寞,JSON是地下黨們用來書寫和交換情報的“暗號”贞瞒,而JSONP則是把用暗號書寫的情報傳遞給自己同志時使用的接頭方式〕寐看到沒军浆?一個是描述信息的格式,一個是信息傳遞雙方約定的方法挡闰。

既然隨便聊聊乒融,那我們就不再采用教條的方式來講述,而是把關注重心放在幫助開發(fā)人員理解是否應當選擇使用以及如何使用上摄悯。

什么是JSON赞季?

前面簡單說了一下,JSON是一種基于文本的數(shù)據交換方式奢驯,或者叫做數(shù)據描述格式申钩,你是否該選用他首先肯定要關注它所擁有的優(yōu)點。

JSON的優(yōu)點:

1瘪阁、基于純文本撒遣,跨平臺傳遞極其簡單;

2管跺、Javascript原生支持义黎,后臺語言幾乎全部支持;

3伙菜、輕量級數(shù)據格式轩缤,占用字符數(shù)量極少,特別適合互聯(lián)網傳遞贩绕;

4火的、可讀性較強,雖然比不上XML那么一目了然淑倾,但在合理的依次縮進之后還是很容易識別的馏鹤;

5、容易編寫和解析娇哆,當然前提是你要知道數(shù)據結構湃累;

JSON的缺點當然也有勃救,但在作者看來實在是無關緊要的東西,所以不再單獨說明治力。

JSON的格式或者叫規(guī)則:

JSON能夠以非常簡單的方式來描述數(shù)據結構蒙秒,XML能做的它都能做,因此在跨平臺方面兩者完全不分伯仲宵统。

1晕讲、JSON只有兩種數(shù)據類型描述符,大括號{}和方括號[]马澈,其余英文冒號:是映射符瓢省,英文逗號,是分隔符,英文雙引號""是定義符痊班。

2勤婚、大括號{}用來描述一組“不同類型的無序鍵值對集合”(每個鍵值對可以理解為OOP的屬性描述),方括號[]用來描述一組“相同類型的有序數(shù)據集合”(可對應OOP的數(shù)組)涤伐。

3馒胆、上述兩種集合中若有多個子項,則通過英文逗號,進行分隔废亭。

4国章、鍵值對以英文冒號:進行分隔,并且建議鍵名都加上英文雙引號""豆村,以便于不同語言的解析液兽。

5、JSON內部常用數(shù)據類型無非就是字符串掌动、數(shù)字四啰、布爾、日期粗恢、null 這么幾個柑晒,字符串必須用雙引號引起來,其余的都不用眷射,日期類型比較特殊匙赞,這里就不展開講述了,只是建議如果客戶端沒有按日期排序功能需求的話妖碉,那么把日期時間直接作為字符串傳遞就好涌庭,可以省去很多麻煩。

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;

關于JSON欧宜,就說這么多坐榆,更多細節(jié)請在開發(fā)過程中查閱資料深入學習。


什么是JSONP冗茸?

先說說JSONP是怎么產生的:

其實網上關于JSONP的講解有很多席镀,但卻千篇一律匹中,而且云里霧里,對于很多剛接觸的人來講理解起來有些困難豪诲,小可不才顶捷,試著用自己的方式來闡釋一下這個問題,看看是否有幫助跛溉。

1焊切、一個眾所周知的問題扮授,Ajax直接請求普通文件存在跨域無權限訪問的問題芳室,甭管你是靜態(tài)頁面、動態(tài)網頁刹勃、web服務堪侯、WCF,只要是跨域請求荔仁,一律不準伍宦;

2、不過我們又發(fā)現(xiàn)乏梁,Web頁面上調用js文件時則不受是否跨域的影響(不僅如此次洼,我們還發(fā)現(xiàn)凡是擁有"src"這個屬性的標簽都擁有跨域的能力,比如遇骑、卖毁、);

3落萎、于是可以判斷亥啦,當前階段如果想通過純web端(ActiveX控件、服務端代理练链、屬于未來的HTML5之Websocket等方式不算)跨域訪問數(shù)據就只有一種可能翔脱,那就是在遠程服務器上設法把數(shù)據裝進js格式的文件里,供客戶端調用和進一步處理媒鼓;

4届吁、恰巧我們已經知道有一種叫做JSON的純字符數(shù)據格式可以簡潔的描述復雜數(shù)據,更妙的是JSON還被js原生支持绿鸣,所以在客戶端幾乎可以隨心所欲的處理這種格式的數(shù)據疚沐;

5、這樣子解決方案就呼之欲出了枚驻,web客戶端通過與調用腳本一模一樣的方式濒旦,來調用跨域服務器上動態(tài)生成的js格式文件(一般以JSON為后綴),顯而易見再登,服務器之所以要動態(tài)生成JSON文件尔邓,目的就在于把客戶端需要的數(shù)據裝入進去晾剖。

6、客戶端在對JSON文件調用成功之后梯嗽,也就獲得了自己所需的數(shù)據齿尽,剩下的就是按照自己需求進行處理和展現(xiàn)了,這種獲取遠程數(shù)據的方式看起來非常像AJAX灯节,但其實并不一樣循头。

7、為了便于客戶端使用數(shù)據炎疆,逐漸形成了一種非正式傳輸協(xié)議卡骂,人們把它稱作JSONP,該協(xié)議的一個要點就是允許用戶傳遞一個callback參數(shù)給服務端形入,然后服務端返回數(shù)據時會將這個callback參數(shù)作為函數(shù)名來包裹住JSON數(shù)據全跨,這樣客戶端就可以隨意定制自己的函數(shù)來自動處理返回數(shù)據了。

如果對于callback參數(shù)如何使用還有些模糊的話亿遂,我們后面會有具體的實例來講解浓若。

JSONP的客戶端具體實現(xiàn):

不管jQuery也好,extjs也罷,又或者是其他支持jsonp的框架,他們幕后所做的工作都是一樣的押蚤,下面我來循序漸進的說明一下jsonp在客戶端的實現(xiàn):

1、我們知道碌上,哪怕跨域js文件中的代碼(當然指符合web腳本安全策略的),web頁面也是可以無條件執(zhí)行的挽放。

遠程服務器remoteserver.com根目錄下有個remote.js文件代碼如下:

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

本地服務器localserver.com下有個jsonp.html頁面代碼如下:

<!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></title> <script type="text/javascript" src="http://remoteserver.com/remote.js"></script></head><body></body></html>

毫無疑問绍赛,頁面將會彈出一個提示窗體,顯示跨域調用成功辑畦。

2吗蚌、現(xiàn)在我們在jsonp.html頁面定義一個函數(shù),然后在遠程remote.js中傳入數(shù)據進行調用纯出。

jsonp.html頁面代碼如下:

<!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></title> <script type="text/javascript"> var localHandler = function(data){ alert('我是本地函數(shù)蚯妇,可以被跨域的remote.js文件調用,遠程js帶來的數(shù)據是:' + data.result); }; </script> <script type="text/javascript" src="http://remoteserver.com/remote.js"></script></head><body></body></html>

remote.js文件代碼如下:

localHandler({"result":"我是遠程js帶來的數(shù)據"});

運行之后查看結果暂筝,頁面成功彈出提示窗口箩言,顯示本地函數(shù)被跨域的遠程js調用成功,并且還接收到了遠程js帶來的數(shù)據焕襟。很欣喜陨收,跨域遠程獲取數(shù)據的目的基本實現(xiàn)了,但是又一個問題出現(xiàn)了,我怎么讓遠程js知道它應該調用的本地函數(shù)叫什么名字呢务漩?畢竟是jsonp的服務者都要面對很多服務對象拄衰,而這些服務對象各自的本地函數(shù)都不相同啊饵骨?我們接著往下看翘悉。

3、聰明的開發(fā)者很容易想到居触,只要服務端提供的js腳本是動態(tài)生成的就行了唄妖混,這樣調用者可以傳一個參數(shù)過去告訴服務端“我想要一段調用XXX函數(shù)的js代碼,請你返回給我”轮洋,于是服務器就可以按照客戶端的需求來生成js腳本并響應了制市。

看jsonp.html頁面的代碼:


這次的代碼變化比較大,不再直接把遠程js文件寫死砖瞧,而是編碼實現(xiàn)動態(tài)查詢息堂,而這也正是jsonp客戶端實現(xiàn)的核心部分,本例中的重點也就在于如何完成jsonp調用的全過程块促。

我們看到調用的url中傳遞了一個code參數(shù),告訴服務器我要查的是CA1998次航班的信息床未,而callback參數(shù)則告訴服務器竭翠,我的本地回調函數(shù)叫做flightHandler,所以請把查詢結果傳入這個函數(shù)中進行調用薇搁。

OK斋扰,服務器很聰明,這個叫做flightResult.aspx的頁面生成了一段這樣的代碼提供給jsonp.html(服務端的實現(xiàn)這里就不演示了啃洋,與你選用的語言無關传货,說到底就是拼接字符串):

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

我們看到,傳遞給flightHandler函數(shù)的是一個json宏娄,它描述了航班的基本信息问裕。運行一下頁面,成功彈出提示窗口孵坚,jsonp的執(zhí)行全過程順利完成粮宛!

4、到這里為止的話卖宠,相信你已經能夠理解jsonp的客戶端實現(xiàn)原理了吧巍杈?剩下的就是如何把代碼封裝一下,以便于與用戶界面交互扛伍,從而實現(xiàn)多次和重復調用筷畦。

什么?你用的是jQuery刺洒,想知道jQuery如何實現(xiàn)jsonp調用鳖宾?好吧亚斋,那我就好人做到底,再給你一段jQuery使用jsonp的代碼(我們依然沿用上面那個航班信息查詢的例子攘滩,假定返回jsonp結果不變):

是不是有點奇怪帅刊?為什么我這次沒有寫flightHandler這個函數(shù)呢?而且竟然也運行成功了漂问!哈哈赖瞒,這就是jQuery的功勞了,jquery在處理jsonp類型的ajax時(還是忍不住吐槽蚤假,雖然jquery也把jsonp歸入了ajax栏饮,但其實它們真的不是一回事兒),自動幫你生成回調函數(shù)并把數(shù)據取出來供success屬性方法來調用磷仰,是不是很爽呀袍嬉?

好啦,寫到這里灶平,我已經無力再寫下去伺通,又困又累,得趕緊睡覺逢享。朋友們要是看這不錯罐监,覺得有啟發(fā),給點個“推薦”唄瞒爬!由于實在比較簡單弓柱,所以就不再提供demo源碼下載了。

4月20日下午的補充:

沒想到上了博客園的頭條推薦侧但∈缚眨看到大家對這篇文章的認可和評論,還是很開心的禀横,這里針對ajax與jsonp的異同再做一些補充說明:

1屁药、ajax和jsonp這兩種技術在調用方式上“看起來”很像,目的也一樣燕侠,都是請求一個url者祖,然后把服務器返回的數(shù)據進行處理,因此jquery和ext等框架都把jsonp作為ajax的一種形式進行了封裝绢彤;

2七问、但ajax和jsonp其實本質上是不同的東西。ajax的核心是通過XmlHttpRequest獲取非本頁內容茫舶,而jsonp的核心則是動態(tài)添加標簽來調用服務器提供的js腳本械巡。

3、所以說,其實ajax與jsonp的區(qū)別不在于是否跨域讥耗,ajax通過服務端代理一樣可以實現(xiàn)跨域有勾,jsonp本身也不排斥同域的數(shù)據的獲取。

4古程、還有就是蔼卡,jsonp是一種方式或者說非強制性協(xié)議,如同ajax一樣挣磨,它也不一定非要用json格式來傳遞數(shù)據雇逞,如果你愿意,字符串都行茁裙,只不過這樣不利于用jsonp提供公開服務塘砸。

總而言之,jsonp不是ajax的一個特例晤锥,哪怕jquery等巨頭把jsonp封裝進了ajax掉蔬,也不能改變著一點!

作者:戰(zhàn)神飄雪

鏈接:http://www.reibang.com/p/860ffb8f8826

來源:簡書

簡書著作權歸作者所有矾瘾,任何形式的轉載都請聯(lián)系作者獲得授權并注明出處女轿。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市霜威,隨后出現(xiàn)的幾起案子谈喳,更是在濱河造成了極大的恐慌,老刑警劉巖戈泼,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赏僧,居然都是意外死亡大猛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門淀零,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挽绩,“玉大人,你說我怎么就攤上這事驾中“埃” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵肩民,是天一觀的道長唠亚。 經常有香客問我,道長持痰,這世上最難降的妖魔是什么灶搜? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上割卖,老公的妹妹穿的比我還像新娘前酿。我一直安慰自己,他們只是感情好鹏溯,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布罢维。 她就那樣靜靜地躺著,像睡著了一般丙挽。 火紅的嫁衣襯著肌膚如雪肺孵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天取试,我揣著相機與錄音悬槽,去河邊找鬼。 笑死瞬浓,一個胖子當著我的面吹牛初婆,可吹牛的內容都是我干的。 我是一名探鬼主播猿棉,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼磅叛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了萨赁?” 一聲冷哼從身側響起弊琴,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎杖爽,沒想到半個月后敲董,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡慰安,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年腋寨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片化焕。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡萄窜,死狀恐怖,靈堂內的尸體忽然破棺而出撒桨,到底是詐尸還是另有隱情查刻,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布凤类,位于F島的核電站穗泵,受9級特大地震影響,放射性物質發(fā)生泄漏踱蠢。R本人自食惡果不足惜火欧,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一棋电、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苇侵,春花似錦赶盔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至陡鹃,卻和暖如春烘浦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萍鲸。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工闷叉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脊阴。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓握侧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嘿期。 傳聞我的和親對象是個殘疾皇子品擎,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內容