json與jsonp區別淺析(json纔是目的,jsonp只是手段)

一言以蔽之,json返回的是一串數據;而jsonp返回的是腳本代碼(包含一個函數調用);javascript

JSON其實就是JavaScript中的一個對象,跟var obj={}在質上徹底同樣,只是在量上能夠無限擴展。簡單地講,json其實就是JavaScript中的對象(Object)和數組(Array,其實也是對象)這倆好基友在那兒你嵌我我嵌你地套上n多層,以此模擬出許多複雜的數據結構。php

json易於人閱讀和編寫,也易於機器解析和生成,相對網絡傳輸速率較高,功能型網站先後端每每要頻繁大量交換數據,而json憑藉其強大的表現力和高顏值漸漸地成爲理想的先後端數據交換語言。那xml前輩呢,我以爲應該會像微軟的xp那樣功成身退。html

同源(不懂同源策略的童鞋請自行百度)下的先後端數據交換格式肯定使用json了,那麼問題來了,若是我想獲取別人網站上提供的數據腫麼作到呢?也就是跨域讀取數據問題(不要鑽牛角說你不須要讀取其餘網站的數據,相信我,你遲早得須要),json行不行呢?答案是No Way,爲何呢,由於json只是普通的文本格式,能讓你這樣就輕鬆拿到那服務端就沒有任何安全和保密性可言了,這樣的話互聯網世界非亂套不可,這個問題那些牛X的規範制定者早就想到了,因此使用了同源策略來限制文件獲取。最後的結果就是隻有像img、script、iframe這類能夠指定src屬性的標籤有跨域獲取別人網站上數據(圖片,腳本,源文件其實都是數據)的能力。好比:java

<!--京東商品圖片-->
<img src="http://img30.360buyimg.com/jgsq-productsoa/jfs/t2407/323/1635505465/47386/f2d89d88/56615e00N7a475ee6.jpg" />
<!--百度CDN-->
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>

看來直接獲取json是行不通了,那有沒有其餘方法能拿到數據呢?因而乎jsonp就這樣被聰明的開發者給發現了,爲何說是發現而不是發明呢,由於並無涉及到任何新技術,就像發現ajax同樣。jquery

jsonp原理是這樣的,網站A須要獲取網站B的數據,網站B說我給大家一個方法,【1. 大家使用<script src="http://www.B.com/open.js"></script>標籤先獲取到open.js文件(網站B的責任),這裏邊有大家須要的數據。2. 大家獲取數據後處理數據(總得處理數據吧)的方法名必須命名爲foo(數據請求者的責任和義務)】,這裏至關於B網站和請求獲取數據者之間創建了一個協議,要求請求者務必按照規則辦事,若是請求者不能同時遵照上面兩條就不能按預期獲取數據。額..,這也算至關於創建了一個潛規則吧ajax

open.js內容json

foo({"name":"B","age":23});  //爲何不直接寫成json數據{"name":"B","age":23}呢,緣由很簡單,在js文件總得合乎js語法吧
//這也是爲何協議中明確規定處理數據的方法名必須命名爲foo,由於B網站是在假定請求者的腳本中已經定義了數據處理方法foo的狀況下返回數據;
//否則就會報foo is not defined錯誤

網站A腳本須有後端

function foo(data){
    console.log(data);
    //ToDo..  
}

啊!雖然拐了個彎,但數據總算獲得了,網站A,網站B都很是高興,那麼問題又來了,網站C說也須要獲取網站B的數據,網站B把協議甩給它,網站C拿過來一看,草泥馬啊,foo這個名字已經在本身的腳本文件的6868行用過了,並且已經使用在腳本的各個角落,批量替換會致使不少潛在bug啊,網站B情急之下決定把foo改爲fool,網站A立馬蹦起來,由於本身的網站已經在不少地方使用foo引用了數據。跨域

爲了不上面狀況發生,那些牛X哄哄的開發者使用了動態生成js文件的方法,php版本以下:數組

open.php

<?php
header('Content-type: application/javascript');
$jsonCallback = htmlspecialchars($_REQUEST ['callback']);    //獲取請求者自定義的回調函數名
$jsonData ='{"name":"B","age":23}';    //待返回的json數據
echo $jsonCallback . "(" . $jsonData . ")";    //輸出jsonp格式的數據,即一行函數調用語句
?>

額 ..,至於php爲何能返回js格式文件,自行百度。
因而網站A用<script src="http://www.B.com/open.php?callback=foo"></script>來請求數據,不須要修改任何變量,返回給A的腳本文件內容是: 

foo({"name":"B","age":23});  //所謂的jsonp,就是一句函數調用,數據都被包裹傳遞到參數中了,千萬別穿個馬甲就不認識了

網站C就用<script src="http://www.B.com/open.php?callback=blah"></script>來請求數據,返回給C的腳本文件內容是:

blah({"name":"B","age":23});

網站N就用<script src="http://www.B.com/open.php?callback=what"></script>來請求數據,返回給N的腳本文件內容是:

what({"name":"B","age":23});

Problem Solved,你們都取到了指望的數據,而且避免了命名衝突。

jsonp全名叫作json with padding,很形象,就是把json對象用符合js語法的形式包裹起來以使其它網站能夠請求獲得,也就是將json數據封裝成js文件;

json是理想的數據交換格式,但沒辦法跨域直接獲取,因而就將json包裹(padding)在一個合法的js語句中做爲js文件傳過去。這就是json和jsonp的區別,json是想要的東西,jsonp是達到這個目的而廣泛採用的一種方法,固然最終得到和處理的仍是json。因此說json是目的,jsonp只是手段。json總會用到,而jsonp只有在跨域獲取數據纔會用到。

理解了json和jsonp的區別以後,其實ajax裏的跨域獲取數據就很好理解和實現了,同源時候並無什麼特別的,直接取就行,跨域時候須要拐個彎來達到目的。

附上jquery中ajax請求json數據實例:

(同源):

$.ajax({
    url:"persons.json",
    success:function(data){
    console.log(data);
     //ToDo..
  }
});

(跨域)

$.ajax({
    url:"http://www.B.com/open.php?callback=?",
    dataType:"jsonp",
    success:function(data){
        console.log(data);
        //ToDo..
    }
});    

jquery已把jsonp封裝進ajax,很合理,由於畢竟絕大多數的jsonp請求都是ajax,關於jquery的ajax具體用法請自行百度,另外要注意的一點就是不一樣的網站提供的數據接口的$_REQUEST ['callback']中不必定絕對是callback也多是cb,cbk等,具體使用時務必閱讀服務端提供的有關接口使用的詳細文檔。

相關文章
相關標籤/搜索