1. 程式人生 > >簡單的json和jsonp

簡單的json和jsonp

 前言

  由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的資料互動行為幾乎只能通過AJAX來實現。

  當然了,通過呼叫強大的PhoneGap外掛然後打包,你可以實現100%的Socket通訊和本地資料庫功能,又或者通過HTML5的WebSocket也可以實現與伺服器的通訊和服務端推功能,但這兩種方式都有其侷限性,前者需要PhoneGap支援,後者要求使用者裝置必須支援WebSocket,因此都不能算是ST2的原生解決方案,原生的只有AJAX。

  說到AJAX就會不可避免的面臨兩個問題,第一個是AJAX以何種格式來交換資料?第二個是跨域的需求如何解決?這兩個問題目前都有不同的解決方案,比如資料可以用自定義字串或者用XML來描述,跨域可以通過伺服器端代理來解決。

  但到目前為止最被推崇或者說首選的方案還是用JSON來傳資料,靠JSONP來跨域。而這就是本文將要講述的內容。

  JSON(JavaScript Object Notation)和JSONP(JSON with Padding)雖然只有一個字母的差別,但其實他們根本不是一回事兒:JSON是一種資料交換格式,而JSONP是一種依靠開發人員的聰明才智創造出的一種非官方跨域資料互動協議。我們拿最近比較火的諜戰片來打個比方,JSON是地下黨們用來書寫和交換情報的“暗號”,而JSONP則是把用暗號書寫的情報傳遞給自己同志時使用的接頭方式。看到沒?一個是描述資訊的格式,一個是資訊傳遞雙方約定的方法。

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

  什麼是JSON

  前面簡單說了一下,JSON是一種基於文字的資料交換方式,或者叫做資料描述格式,你是否該選用他首先肯定要關注它所擁有的優點。

  JSON的優點:

  1、基於純文字,跨平臺傳遞極其簡單;

  2、Javascript原生支援,後臺語言幾乎全部支援;

  3、輕量級資料格式,佔用字元數量極少,特別適合網際網路傳遞;

  4、可讀性較強,雖然比不上XML那麼一目瞭然,但在合理的依次縮排之後還是很容易識別的;

  5、容易編寫和解析,當然前提是你要知道資料結構;

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

  JSON的格式或者叫規則:

  JSON能夠以非常簡單的方式來描述資料結構,XML能做的它都能做,因此在跨平臺方面兩者完全不分伯仲。

  1、JSON只有兩種資料型別描述符,大括號{}和方括號[],其餘英文冒號:是對映符,英文逗號,是分隔符,英文雙引號""是定義符。

  2、大括號{}用來描述一組“不同型別的無序鍵值對集合”(每個鍵值對可以理解為OOP的屬性描述),方括號[]用來描述一組“相同型別的有序資料集合”(可對應OOP的陣列)。

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

  4、鍵值對以英文冒號:進行分隔,並且建議鍵名都加上英文雙引號”",以便於不同語言的解析。

  5、JSON內部常用資料型別無非就是字串、數字、布林、日期、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,就說這麼多,更多細節請在開發過程中查閱資料深入學習。

  什麼是JSONP

  先說說JSONP是怎麼產生的:

  其實網上關於JSONP的講解有很多,但卻千篇一律,而且雲裡霧裡,對於很多剛接觸的人來講理解起來有些困難,小可不才,試著用自己的方式來闡釋一下這個問題,看看是否有幫助。

  1、一個眾所周知的問題,Ajax直接請求普通檔案存在跨域無許可權訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一律不準;

  2、不過我們又發現,Web頁面上呼叫js檔案時則不受是否跨域的影響(不僅如此,我們還發現凡是擁有”src”這個屬性的標籤都擁有跨域的能力,比如<script>、<img>、<iframe>);

  3、於是可以判斷,當前階段如果想通過純web端(ActiveX控制元件、服務端代理、屬於未來的HTML5之Websocket等方式不算)跨域訪問資料就只有一種可能,那就是在遠端伺服器上設法把資料裝進js格式的檔案裡,供客戶端呼叫和進一步處理;

  4、恰巧我們已經知道有一種叫做JSON的純字元資料格式可以簡潔的描述複雜資料,更妙的是JSON還被js原生支援,所以在客戶端幾乎可以隨心所欲的處理這種格式的資料;

  5、這樣子解決方案就呼之欲出了,web客戶端通過與呼叫指令碼一模一樣的方式,來呼叫跨域伺服器上動態生成的js格式檔案(一般以JSON為字尾),顯而易見,伺服器之所以要動態生成JSON檔案,目的就在於把客戶端需要的資料裝入進去。

  6、客戶端在對JSON檔案呼叫成功之後,也就獲得了自己所需的資料,剩下的就是按照自己需求進行處理和展現了,這種獲取遠端資料的方式看起來非常像AJAX,但其實並不一樣。

  7、為了便於客戶端使用資料,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許使用者傳遞一個callback引數給服務端,然後服務端返回資料時會將這個callback引數作為函式名來包裹住JSON資料,這樣客戶端就可以隨意定製自己的函式來自動處理返回資料了。

  如果對於callback引數如何使用還有些模糊的話,我們後面會有具體的例項來講解。

  JSONP的客戶端具體實現:

  不管jQuery也好,ExtJs也罷,又或者是其他支援jsonp的框架,他們幕後所做的工作都是一樣的,下面我來循序漸進的說明一下jsonp在客戶端的實現:

  1、我們知道,哪怕跨域js檔案中的程式碼(當然指符合web指令碼安全策略的),web頁面也是可以無條件執行的。

  遠端伺服器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、現在我們在jsonp.html頁面定義一個函式,然後在遠端remote.js中傳入資料進行呼叫。

  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('我是本地函式,可以被跨域的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的服務者都要面對很多服務物件,而這些服務物件各自的本地函式都不相同啊?我們接著往下看。

  3、聰明的開發者很容易想到,只要服務端提供的js指令碼是動態生成的就行了唄,這樣呼叫者可以傳一個引數過去告訴服務端“我想要一段呼叫XXX函式的js程式碼,請你返回給我”,於是伺服器就可以按照客戶端的需求來生成js指令碼並響應了。

  看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 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客戶端實現的核心部分,本例中的重點也就在於如何完成jsonp呼叫的全過程。

  我們看到呼叫的url中傳遞了一個code引數,告訴伺服器我要查的是CA1998次航班的資訊,而callback引數則告訴伺服器,我的本地回撥函式叫做flightHandler,所以請把查詢結果傳入這個函式中進行呼叫。

  OK,伺服器很聰明,這個叫做flightResult.aspx的頁面生成了一段這樣的程式碼提供給jsonp.html(服務端的實現這裡就不演示了,與你選用的語言無關,說到底就是拼接字串):

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

  我們看到,傳遞給flightHandler函式的是一個json,它描述了航班的基本資訊。執行一下頁面,成功彈出提示視窗,jsonp的執行全過程順利完成!

  4、到這裡為止的話,相信你已經能夠理解jsonp的客戶端實現原理了吧?剩下的就是如何把程式碼封裝一下,以便於與使用者介面互動,從而實現多次和重複呼叫。

  什麼?你用的是jQuery,想知道jQuery如何實現jsonp呼叫?好吧,那我就好人做到底,再給你一段jQuery使用jsonp的程式碼(我們依然沿用上面那個航班資訊查詢的例子,假定返回jsonp結果不變):

<!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>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
     jQuery(document).ready(function(){
        $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//傳遞給請求處理程式或頁面的,用以獲得jsonp回撥函式名的引數名(一般預設為:callback)
             jsonpCallback:"flightHandler",//自定義的jsonp回撥函式名稱,預設為jQuery自動生成的隨機函式名,也可以寫"?",jQuery會自動為你處理資料
             success: function(json){
                 alert('您查詢到航班資訊:票價: ' + json.price + ' 元,餘票: ' + json.tickets + ' 張。');
             },
             error: function(){
                 alert('fail');
             }
         });
     });
     </script>
     </head>
  <body>
  </body>
 </html>

  是不是有點奇怪?為什麼我這次沒有寫flightHandler這個函式呢?而且竟然也執行成功了!哈哈,這就是jQuery的功勞了,jquery在處理jsonp型別的ajax時(還是忍不住吐槽,雖然jquery也把jsonp歸入了ajax,但其實它們真的不是一回事兒),自動幫你生成回撥函式並把資料取出來供success屬性方法來呼叫,是不是很爽呀?

  這裡,我在補充一下callback,如果createscript函式用來引入一個script,當然src是一個跨域的uri

function CreateScript(src) {
    $("<script><//script>").attr("src", src).appendTo("body")
}

   結果是什麼呢?

image_thumb21

可以看到script請求的內容是能夠訪問載入進來的,但是確實有錯誤的,為什麼呢?

因為原來用script標籤載入完後,會立即 把響應當js去執行,很明顯{"Email":"[email protected]","Remark":"我來自遙遠的東方"}不是合法的js語句。所以會出現錯誤。

顯然,把上面的json放到一個回撥方法裡是最簡單的方法。例如,變成這樣:

image_thumb[8]

如果存在jsonpcallback這個方法,那麼jsonpcallback({"Email":"[email protected]","Remark":"我來自遙遠的東方"})就是合法的js語句。

由於伺服器不知道客戶端的回撥是什麼,不可能hard code成jsonpcallback,所以就帶一個QueryString讓客戶端告訴服務端,回撥方法是什麼,當然,QueryString的key要遵從服務端的約定,上面的是”callback“。

添加回調函式:

function jsonpcallback(json) {
    console.log(json)
}

把前面的方法稍微改改引數:

$("#getJsonpByHand").click(function () {
    CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")
})
image_thumb[8]

200OK,伺服器返回jsonpcallback({"Email":"[email protected]","Remark":"我來自遙遠的 東方"}),我們也寫了jsonpcallback方法,當然會執行。OK順利獲得了json。沒錯,到這裡就是jsonp的全部。

 補充

  1、ajax和jsonp這兩種技術在呼叫方式上“看起來”很像,目的也一樣,都是請求一個url,然後把伺服器返回的資料進行處理,因此jquery和ext等框架都把jsonp作為ajax的一種形式進行了封裝;

  2、但ajax和jsonp其實本質上是不同的東西。ajax的核心是通過XmlHttpRequest獲取非本頁內容,而jsonp的核心則是動態新增<script>標籤來呼叫伺服器提供的js指令碼。

  3、所以說,其實ajax與jsonp的區別不在於是否跨域,ajax通過服務端代理一樣可以實現跨域,jsonp本身也不排斥同域的資料的獲取。

  4、還有就是,jsonp是一種方式或者說非強制性協議,如同ajax一樣,它也不一定非要用json格式來傳遞資料,如果你願意,字串都行,只不過這樣不利於用jsonp提供公開服務。

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

相關推薦

簡單jsonjsonp

 前言   由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的資料互動行為幾乎只能通過AJAX來實現。   當然了,通過呼叫強大的PhoneGap外掛然後打包,你可以實現100%的Socket通訊和本地資料庫功能,又或者通過HTML5的WebSoc

jsonjsonp

窗口 itl element 服務器 本地服務 設置 定義 鍵值 png json:一種數據交換的格式。 jsonp:一種依靠開發人員的聰明才智創造出的一種非官方跨域數據交互協議。 形象點說,以諜戰片來打個比方,JSON是地下黨們用來書寫和交換情報的“暗號”,而JSONP則

說說JSONJSONP,也許你會豁然開朗

解析 幫助 w3c 為什麽 語言 pad url地址 john object  轉自:http://kb.cnblogs.com/page/139725/      http://kb.cnblogs.com/page/150964/ 前言   由於Sencha

JSONJSONP,原來ajax引用這個來實現跨域訪問的

第一個 下午 想要 進行 ava 客戶 als rep web客戶端 由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的數據交互行為幾乎只能通過AJAX來實現。 當然了,通過調用強大的PhoneGap插件然後打包,你可以實現100%的Socket通訊和本

JSONJSONP的區別

post 原理 sync 我們 語言 comm number 前後端 .com 什麽是JSON? ,JSON是一種輕量級的數據傳輸格式,被廣泛應用於當前Web應用中。JSON格式數據的編碼和解析基本在所有主流語言中都被實現,所以現在大部分前後端分離的架構都以JSON格式進行

同源策略、跨域、jsonjsonp

open 是把 tro 兩個 屬性 ont type cti 結果 同源策略 源(origin)就是協議、域名和端口號。若地址裏面的協議、域名和端口號均相同則屬於同源。 以下是相對於 http://www.a.com/test/index.html 的同源檢測  ? htt

json jsonp

數據 jsonp strong str 添加 span java script 參數 json 是一種數據交換格式 jsonp 是一種數據交換協議 JSONP(JSON with Padding)就是為了讓所有瀏覽器都能夠跨域名調用。 客戶端向URL添加一個回調參數JSON

JSONJSONP (含jQuery實例)(share)

窗口 現在 sync 方括號 彈出 後臺 開始 擁有 逗號 前言: 說到AJAX就會不可避免的面臨兩個問題,第一個是AJAX以何種格式來交換數據?第二個是跨域的需求如何解決?這兩個問題目前都有不同的解決方案,比如數據可以用自定義字符串或者用XML來描述,跨域可以通過服務

jsonjsonp的使用格式

最近一直在看關於json和jsonp的區別和各自的用法、優缺點!  下面是我看到過解釋最清楚的一片文章   說到AJAX就會不可避免的面臨兩個問題,第一個是AJAX以何種格式來交換資料?第二個是跨域的需求如何解決?這兩個問題目前都有不同的解決方案,比如資料可以用自定

ajax中的jsonjsonp詳解

出現的問題: 花了點時間研究ajax中的json和jsonp的原理,這裡記錄一下。以前一直在使用ajax呼叫資料,但是從來沒有遇到跨域問題,也從來沒有注意過json和jsonp的區別,總是一通亂用。但昨天朋友遇到這個問題,讓我幫他研究研究。直接上圖。 然後我的第一反應當然是去找哪裡少一個分號,但是該加分號的

JSONJSONP劫持以及解決方法

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興! json劫持 json劫持攻擊又為”JSON Hijacking”,攻擊過程有點類似於csrf,只不過csrf只管傳送http請求,但是js

說說JSONJSONP區別

前言   由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的資料互動行為幾乎只能通過AJAX來實現。   當然了,通過呼叫強大的PhoneGap外掛然後打包,你可以實現100%的Socket通訊和本地資料庫功能,又或者通過HTML5的WebSocket也可以實現與伺服器的通訊和服務端推功

說說JSONJSONP,跨域解決問題

 前言   由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的資料互動行為幾乎只能通過AJAX來實現。   當然了,通過呼叫強大的PhoneGap外掛然後打包,你可以實現100%的Socket通訊和本地資料庫功能,又或者通過HTML5的WebSoc

JSONJSONP理解

這是Google排名第一的答案,看完以後非常清晰,在這裡標記一下,怕以後找不到 http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 總的來說就是: JSON是一種傳遞資料的資料結構 優點

淺談JSONJSONP的區別

以前經常把JSON和JSONP搞混淆,最近特意查閱了相關資料終於搞明白兩者關係了,簡單說一下。 JSON JSON是一種基於文字的資料交換格式,用於描述複雜的資料,舉個例子,描述一個學生的資訊可以這樣子寫: var student = { "i

說說JSONJSONP,也許你會豁然開朗,含jQuery用例

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://w

jsonjsonP的區別聯絡以及ajaxjsonP的區別

json和jsonP雖然只有一個字母的區別,但是他們之間扯不上關係。 json是一種輕量級的資料交換格式。 jsonp是一種跨域資料互動協議。 json的優點:(1)基於純文字傳遞極其簡單,(2)輕量級資料格式適合網際網路傳遞,(3)容易編寫和解析。 ajax和jsonp

jsonjsonp區別

JSON例項:// 描述一個人 var person = { "Name": "Bob", "Age": 32, "Company": "IBM", "Engineer": true } // 獲取這個人的資訊 var personAge = person.Age;

淺談jsonjsonp

 前言   由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的資料互動行為幾乎只能通過AJAX來實現。   當然了,通過呼叫強大的PhoneGap外掛然後打包,你可以實現100%的Socket通訊和本地資料庫功能,又或者通過HTML5的WebSoc

說說JSONJSONP,也許你會豁然開朗,含jQuery用例

前言: 由於Sencha Touch 2這種開發模式的特性,基本決定了它原生的資料互動行為幾乎只能通過AJAX來實現。 當然了,通過呼叫強大的PhoneGap外掛然後打包,你可以實現100%的Socket通訊和本地資料庫功能,又或者通過HTML5的WebSocket也可