摘要:本文討論了結(jié)合使用JSON和Dynamic script Tag技術(shù)來解決Ajax應(yīng)用中跨域訪問第三方Web服務(wù)的問題。
關(guān)鍵詞:Ajax;JSON;動態(tài)script標(biāo)簽;跨域
1 引言
當(dāng)前多數(shù)的Web服務(wù)都是采用XML作為數(shù)據(jù)交換格式。因此當(dāng)我們在Ajax應(yīng)用中會使用XMLHttpRequest對象來訪問Web服務(wù)的時候就會遇到跨域限制問題。
跨域問題的實質(zhì)是由于瀏覽器對JavaScript腳本的安全限制使得在Ajax應(yīng)用中只能訪問本域的Web服務(wù)。我們通常選用的解決方案是在本域的服務(wù)器上建立一個跨域代理(Cross Domain Proxy)來間接的訪問第三放Web服務(wù)。但是跨域代理需要在本域的服務(wù)器上運行,不僅浪費服務(wù)器資源,而且也增加了開發(fā)和維護成本。如果我們在編寫Web服務(wù)的時候放棄XML作為數(shù)據(jù)交換格式,而采用JSON(JavaScript Object Notation)數(shù)據(jù)交換格式,那么將能夠利用動態(tài)建立script標(biāo)簽的方式來規(guī)避跨域限制。
2 動態(tài)script標(biāo)簽技術(shù)
我們知道,script標(biāo)簽是屬于HTML標(biāo)簽,而HTML標(biāo)簽是沒有跨域限制的。從而我們可以使用script標(biāo)簽中的src屬性來訪問其他任意域的URL鏈接來獲取數(shù)據(jù)。
文檔對象模型(DOM,Document Object Model)為我們提供了動態(tài)建立script標(biāo)簽的能力。我們可以在需要的時候使用document.createElement()方法來建立一個script標(biāo)簽對象,并使用setAttribute()方法來設(shè)定它的src、id、type、language等屬性,這樣當(dāng)我們使用appendChild()方法將這個剛剛建立的script標(biāo)簽添加到網(wǎng)頁中后,我們就能夠得到這個script標(biāo)簽src屬性的URL所返回的數(shù)據(jù)。
3 JSON數(shù)據(jù)交換格式
Web服務(wù)使用XML作為數(shù)據(jù)交換格式是不能用script標(biāo)簽訪問Web服務(wù)并獲取數(shù)據(jù)的。但如果Web服務(wù)使用JSON作為數(shù)據(jù)交換格式就不會存在這個問題了。
3.1 JSON的定義
JSON建構(gòu)于兩種結(jié)構(gòu):
“名稱/值”對的集合(A collection of name/value pairs)。不同的語言中,它被理解為對象(object),紀(jì)錄(record),結(jié)構(gòu)(struct),字典(dictionary),哈希表(hash table),有鍵列表(keyed list),或者關(guān)聯(lián)數(shù)組 (associative array)。
值的有序列表(An ordered list of values)。在大部分語言中,它被理解為數(shù)組(array)。
簡單來說,JSON實際上是利用現(xiàn)代編程語言大多支持的一些基本數(shù)據(jù)結(jié)構(gòu),例如數(shù)組、字符串、對象等。進行抽象而來的一種通用數(shù)據(jù)表述格式。這使得JSON數(shù)據(jù)格式在能夠支持這些數(shù)據(jù)結(jié)構(gòu)的編程語言之間能夠進行數(shù)據(jù)的交換。
3.2JSON格式舉例
使用XML格式表示一個學(xué)生的姓名、學(xué)號、成績等信息,可能如下:
<?xml version=“1.0”?>
<students>
<student>
<name>張三</name>
<studentID>200801</studentID>
<grade>80</grade>
</student>
<student>
<name>李四</name>
<studentID>200802</studentID>
<grade>90</grade>
</student>
</students>
上述XML轉(zhuǎn)換為JSON格式表示:
var StudentsJSON = {
student:[
{
name:'張三',
studentid:200801,
grade:80
},
{
name:'李四',
studentid:200802,
grade:90
}
]
}
從上面的例子中我們可以看出,XML和JSON有比較好的對應(yīng)關(guān)系,XML數(shù)據(jù)可以非常容易的轉(zhuǎn)換到JSON。事實也正是如此,大多數(shù)的XML數(shù)據(jù)再轉(zhuǎn)換為JSON的時候都不會有問題。例如在http://www.thomasfrank.se/xml_to_json.html網(wǎng)站中就提供一個自動進行XML to JSON轉(zhuǎn)換的JavaScript腳本。
3.3 JSON數(shù)據(jù)的訪問
JSON數(shù)據(jù)的訪問相對于XML要簡單很多??梢匀缤琂avaScript對象一樣訪問JSON數(shù)據(jù)。例如在上述JSON數(shù)據(jù)中,我們要訪問第一個學(xué)生的姓名,只要寫:StudentsJSON.student[0].name就可以了。要訪問第二個同學(xué)的學(xué)號:StudentsJSON.student[1].studentid
4 實例研究
雅虎為我們提供了一個圖片搜索Web服務(wù),URL為:http://search.yahooapis.com/ImageSearchService/V1/imageSearch。這個Web服務(wù)支持返回JSON格式數(shù)據(jù)。該Web服務(wù)接受的參數(shù)為如下:
只要動態(tài)構(gòu)建該URL并加入動態(tài)創(chuàng)建的script標(biāo)簽中的src屬性中即可獲得Web服務(wù)返回的JSON數(shù)據(jù)。查詢的結(jié)果都在ResultSet.Result[0]數(shù)組中。
當(dāng)我們構(gòu)建好查詢網(wǎng)頁后,可以在本機上用IE或Firefox等瀏覽器直接打開該網(wǎng)頁并測試。
5 實驗結(jié)果及比較
可以看到采用動態(tài)script標(biāo)簽技術(shù)結(jié)合JSON數(shù)據(jù)交換格式的方法使得跨域訪問Web服務(wù)非常的容易。然而在Web服務(wù)中使用JSON數(shù)據(jù)交換格式相對于XML又有那些優(yōu)缺點呢?下面從五個方面進行分析:
可讀性:JSON和XML的可讀性可謂不相上下,JSON采用常見的語法數(shù)據(jù)結(jié)構(gòu),XML使用的是規(guī)范的標(biāo)簽形式。
可擴展性:XML天生有很好的擴展性,而JSON也不遜于XML。
編碼難度:XML有豐富的編碼工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的編碼明顯比XML容易許多,即使不借助工具也能寫出JSON的代碼,可是要寫好XML就不太容易了。
解碼難度:XML的解析得考慮子節(jié)點父節(jié)點,讓人頭昏眼花,而JSON的解析難度幾乎為0。這一點XML輸?shù)恼媸菦]話說。
流行度:XML已經(jīng)被業(yè)界廣泛的使用,而JSON才剛剛開始,但是在Ajax這個特定的領(lǐng)域,未來的發(fā)展也許XML要讓位于JSON。到時Ajax就應(yīng)該變成Ajaj (Asynchronous JavaScript and JSON)了。
參考文獻
[1]json. json.org. http://www.json.org/json-zh.html
[2]Nicholas C. Zakas. JavaScript高級程序設(shè)計. 人民郵電出版社,2006年