JSON是一種資料交換格式,而JSONP是一種依靠開發人員的聰明才智創造出的一種非官方跨域資料互動協定,本文從理論到實踐詳細的講解了JSON和JSONP的使用
什麼是Json?
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一個子集。 JSON采用
完全獨立于語言的文本格式,但是也使用了類似于C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的資料交換語言。易于人
閱讀和編寫,同時也易于機器解析和生成。
JSON有兩種結構:
json簡單說就是javascript中的對象和數組,是以這兩種結構就是對象和數組2種結構,通過這兩種結構可以表示各種複雜的結構
1、對象:對象在js中表示為“{}”擴起來的内容,資料結構為 {key:value,key:value,...}的鍵值對的結構,在面向對象的語言中,key為對象的屬性,value為對應的屬性值,是以很容易了解,取值方法為 對象.key 擷取屬性值,這個屬性值的類型可以是 數字、字元串、數組、對象幾種。
2、數組:數組在js中是中括号“[]”擴起來的内容,資料結構為 ["java","javascript","vb",...],取值方式和所有語言中一樣,使用索引擷取,字段值的類型可以是 數字、字元串、數組、對象幾種。
經過對象、數組2種結構就可以組合成複雜的資料結構了。
JSON的格式或者叫規則:
JSON能夠以非常簡單的方式來描述資料結構,XML能做的它都能做,是以在跨平台方面兩者完全不分伯仲。
1、JSON隻有兩種資料類型描述符,大括号{}和方括号[],其餘英文冒号:是映射符,英文逗号,是分隔符,英文雙引号""是定義符。
2、大括号{}用來描述一組“不同類型的無序鍵值對集合”(每個鍵值對可以了解為OOP的屬性描述),方括号[]用來描述一組“相同類型的有序資料集合”(可對應OOP的數組)。
3、上述兩種集合中若有多個子項,則通過英文逗号,進行分隔。
4、鍵值對以英文冒号:進行分隔,并且建議鍵名都加上英文雙引号"",以便于不同語言的解析。
5、JSON内部常用資料類型無非就是字元串、數字、布爾、日期、null 這麼幾個,字元串必須用雙引号引起來,其餘的都不用,日期類型比較特殊,這裡就不展開講述了,隻是建議如果用戶端沒有按日期排序功能需求的話,那麼把日期時間直接作為字元串傳遞就好,可以省去很多麻煩。
JSON執行個體
複制代碼代碼如下:
// 描述一個人
var Person = {
"Name": "aehyok",
"Age": 25,
"Company": "aehyok",
"Engineer": true
}
//擷取這個人的資訊
var PersonAge = Person.Age;
alert(PersonAge);
//描述幾個人
var members = [
{
"Name": "aehyok",
"Age": 25,
"Company": "aehyok",
"Engineer": true
},
{
"Name": "lqm",
"Age": 25,
"Company": "Oracle",
"Engineer": false
},
{
"Name": "thl",
"Age": 22,
"Company": "Microsoft",
"Engineer": false
}
]
// 讀取其中lqm的公司名稱
var lqmCompany = members[1].Company;
alert(lqmCompany);
// 描述一次會議
var conference = {
"Conference": "Future Marketing",
"Date": "2013-5-22",
"Address": "ShenZhen",
"Members":
[
{
"Name": "aehyok",
"Age": 25,
"Company": "IBM",
"Engineer": true
},
{
"Name": "lqm",
"Age": 25,
"Company": "Oracle",
"Engineer": false
},
{
"Name": "Thl",
"Age": 20,
"Company": "Microsoft",
"Engineer": false
}
]
}
// 讀取參會者Thl是否工程師
var ThlIsAnEngineer = conference.Members[2].Engineer;
alert(ThlIsAnEngineer);
什麼是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的用戶端具體實作 :
1.先來個最簡單的一個。首先我在IIS中建立了兩個網站,當然端口一個是888另外一個是8888,我們就把888作為本地伺服器,8888作為遠端伺服器的。
現在本地有這樣一個網頁
複制代碼代碼如下:
<html>
<head>
<title>index.html</title>
<script type="text/javascript" src="http://localhost:8888/remote.js" ></script>
</head>
<body></body>
</html>
其中JavaScript檔案引用的是8888的remote.js檔案。
複制代碼代碼如下:
alert('我是遠端檔案');
運作本地伺服器網站後效果為
現在最簡單的跨域成功了。
2.我們在1的基礎上進行修改一下,先看代碼
複制代碼代碼如下:
<html>
<head>
<title>index.html</title>
<script type="text/javascript">
function aehyok(data)
{
alert(data.result);
}
</script>
<script type="text/javascript" src="http://localhost:8888/remote.js" ></script>
</head>
<body></body>
</html>
先将本地檔案中添加一個js函數,然後調用遠端伺服器的js檔案。
複制代碼代碼如下:
aehyok({"result":"我是遠端js帶來的資料"});
這是在遠端服務端js檔案中的代碼。
運作後效果
調用成功。顯示本地函數被跨域的遠端js調用成功,并且還接收到了遠端js帶來的資料。很欣喜,跨域遠端擷取資料的目的基本實作了,但是又一個問題出現了,我怎麼讓遠端js知道它應該調用的本地函數叫什麼名字呢?畢竟是jsonp的服務者都要面對很多服務對象,而這些服務對象各自的本地函數都不相同啊?我們接着往下看。
複制代碼代碼如下:
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "get",
async: false,
url: "../Home/aehyok",
dataType: "jsonp",
jsonp: "callback", //傳遞給請求處理程式或頁面的,用以獲得jsonp回調函數名的參數名(一般預設為:callback)
jsonpCallback: "aehyok", //自定義的jsonp回調函數名稱,預設為jQuery自動生成的随機函數名,也可以寫"?",jQuery會自動為你處理資料
success: function (json) {
alert("第二次"+json.result);
},
error: function () {
alert('fail');
}
});
});
function aehyok(data) {
alert("第一次"+data.result);
}
</script>
我是在asp.net mvc3.0項目中,是以背景在控制器中
複制代碼代碼如下:
public string aehyok()
{
return "aehyok({\"result\":\"我是遠端js帶來的資料\"})";
}
然後執行結果為
通過調試可以發現URLhttp://localhost:6247/Home/aehyok?callback=aehyok&_=1369235398641
callback=aehyok就是回調函數,在調用完背景傳回是先執行aehyok(data)。
然後又執行success(json)。是以有兩次的彈窗。
我現在隻不過是在一個項目下進行,其實道理還是一樣的。