雖然XML已在不少應用程序中大顯身手,但它并不是十全十美的,特別是遇到AJAX應用的時(shí)候,XMLHttpRequest會(huì )檢查返回數據的MIME類(lèi)型,如果是text/xml類(lèi)型,XMLHttpRequest就會(huì )運行XML Parser來(lái)解析返回的文檔,并在內存中構建出對應的DOM樹(shù),之后,你可以用JavaScript標準的DOM方法來(lái)操作DOM樹(shù)。由于眾所周知DOM的詬病,這顯然不是有效率的方法。另外一個(gè)問(wèn)題是,如果你想使用JavaScript對象而不是直接用XML數據的話(huà),你還得自己遍歷整個(gè)DOM樹(shù)來(lái)創(chuàng )建相應對象。
于是JSON出現在我們面前。
JSON提供了一種更適合AJAX應用的標準數據交換格式。JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。易于人閱讀和編寫(xiě)。同時(shí)也易于機器解析和生成。
XML和JSON都利用結構化來(lái)標記數據。我們將通過(guò)一個(gè)地址簿的例子來(lái)展示它們之間的不同。
該地址簿用XML如下表示:
代碼
- <?xml version=‘1.0‘ encoding=‘UTF-8‘?>
- <card>
- <fullname>Sean Kelly</fullname>
- <org>SK Consulting</org>
- <emailaddrs>
- <address type=‘work‘>kelly@seankelly.biz</address>
- <address type=‘home‘ pref=‘1‘>kelly@seankelly.tv</address>
- </emailaddrs>
- <telephones>
- <tel type=‘work‘ pref=‘1‘>+1 214 555 1212</tel>
- <tel type=‘fax‘>+1 214 555 1213</tel>
- <tel type=‘mobile‘>+1 214 555 1214</tel>
- </telephones>
- <addresses>
- <address type=‘work‘ format=‘us‘>1234 Main St
- Springfield, TX 78080-1216</address>
- <address type=‘home‘ format=‘us‘>5678 Main St
- Springfield, TX 78080-1316</address>
- </addresses>
- <urls>
- <address type=‘work‘>http://seankelly.biz/ </address>
- <address type=‘home‘>http://seankelly.tv/ </address>
- </urls>
- </card>
在JSON中,則是:
代碼
- {
- "fullname": "Sean Kelly",
- "org": "SK Consulting",
- "emailaddrs": [
- {"type": "work", "value": "kelly@seankelly.biz"},
- {"type": "home", "pref": 1, "value": "kelly@seankelly.tv"}
- ],
- "telephones": [
- {"type": "work", "pref": 1, "value": "+1 214 555 1212"},
- {"type": "fax", "value": "+1 214 555 1213"},
- {"type": "mobile", "value": "+1 214 555 1214"}
- ],
- "addresses": [
- {"type": "work", "format": "us",
- "value": "1234 Main StnSpringfield, TX 78080-1216"},
- {"type": "home", "format": "us",
- "value": "5678 Main StnSpringfield, TX 78080-1316"}
- ],
- "urls": [
- {"type": "work", "value": "http://seankelly.biz/"},
- {"type": "home", "value": "http://seankelly.tv/"}
- ]
- }
JSON提供了兩種結構:
名/值對,其格式如下 {"名":"值", ...} 如:{"fullname": "Sean Kelly"},你可以把它理解為對象,或者哈希表,字典等等。
數組,它是值的有序列表。一個(gè)數組以“[”開(kāi)始,“]”結束。值之間使用“,”分隔。
JSON的值(value)可以是雙引號括起來(lái)的字符串(string)、數值(number)、true、false、 null、對象(object)或者數組(array)。這些結構可以嵌套。
事實(shí)上大部分現代計算機語(yǔ)言都以某種形式支持它們。這使得一種數據格式在同樣基于這些結構的編程語(yǔ)言之間交換成為可能。
在A(yíng)JAX中的XML與JSON之戰
在A(yíng)JAX應用中,你可以用XMLHttpRequest讀取XML或者JSON文件。一個(gè)典型的AJAX調用如下:
代碼
- var req = new XMLHttpRequest();
- req.open("GET", "http://localhost/addr?cardID=32", true);
- req.onreadystatechange = myHandler;
- req.send(null);
Web服務(wù)器應答的時(shí)候,處理子程序(例子中的myHandler)會(huì )反復被調用。
處理地址簿的一個(gè)XML的程序片斷可能是:
代碼
- function myHandler() {
- if (req.readyState == 4 ) {
-
- var addrField = document.getElementById(‘a(chǎn)ddr‘);
- var root = req.responseXML;
- var addrsElem = root.getElementsByTagName(‘a(chǎn)ddresses‘)[0];
- var firstAddr = addrsElem.getElementsByTagName(‘a(chǎn)ddress‘)[0];
- var addrText = fistAddr.firstChild;
- var addrValue = addrText.nodeValue;
- addrField.value = addrValue;
- }
- }
注意:XMLHttpRequest自動(dòng)創(chuàng )建了DOM樹(shù),你可以通過(guò)responseXML屬性訪(fǎng)問(wèn)樹(shù)并進(jìn)行一系列處理,比如通過(guò)getElementsByTagName訪(fǎng)問(wèn)元素。但對于復雜的XML,這是個(gè)煩瑣無(wú)味的活兒!
再看JSON:
代碼
- function myHandler() {
- if (req.readyState == 4 ) {
- var addrField = document.getElementById(‘a(chǎn)ddr‘);
- var card = eval(‘(‘ + req.responseText + ‘)‘);
- addrField.value = card.addresses[0].value;
- }
- }
使用JSON的第一件事,你要手工解析JSON響應,但是請記住,JSON是JavaScript的子集,事實(shí)上你只需要調用一行 eval就可以完成解析工作。接下來(lái)訪(fǎng)問(wèn)JSON的對象就和訪(fǎng)問(wèn)任何JavaScript對象完全一樣:
代碼
- card.addresses[0].value 即"1234 Main Stb &"
- card.addresses[0].type 即"work"
- card.addresses[1] 即home address;
- card.fullname 即 "Sean Kelly"
上千次的測試之后表明,JSON的速度幾乎是XML解析的10倍!
JSON要普及,這里有兩個(gè)問(wèn)題:
1. 有多少服務(wù)器愿意提供JSON格式的輸出?隨著(zhù)JSON的速度優(yōu)勢得到大家的認可,相信會(huì )越來(lái)越多。
2. 執行eval操作可能會(huì )導致安全漏洞。所以最好還是使用一個(gè)JSON解析器,不過(guò)幸運的是。你可以在http://www.json.org找到一個(gè)。未來(lái)JSON的支持可能會(huì )被包括在ECMAScript標準中。