在JavaScript中將JSON的字符串解析成JSON數(shù)據(jù)格式,一般有兩種方式:
一種為使用eval()函數(shù)。
使用Function對象來進行返回解析。
使用eval函數(shù)來解析,jquery的each方法來遍歷
用JQuery解析JSON數(shù)據(jù)的方法,作為JQuery異步請求的傳輸對象,JQuery請求后返回的結(jié)果是json對象,這里考慮的都是服務器返回JSON形式的字符串的形式,對于利用JSONObject等插件封裝的JSON對象,與此亦是大同小異,這里不再做說明。
這里首先給出JSON字符串集,字符串集如下:
var data = "
{
root:
[
{name:'1',value:'0'},
{name:'6101',value:'北京市'},
{name:'6102',value:'天津市'},
{name:'6103',value:'上海市'},
{name:'6104',value:'重慶市'},
]
}";
這里以JQuery異步獲取的數(shù)據(jù)類型——json對象和字符串為依據(jù),分別介紹兩種方式獲取到的結(jié)果處理方式。
eval()
對于服務器返回的JSON字符串,如果jquery異步請求沒做類型說明,或者以字符串方式接受,那么需要做一次對象化處理,方式不是太麻煩,就是將該字符串放于eval()中執(zhí)行一次。這種方式也適合以普通javascipt方式獲取json對象,以下舉例說明:
// 轉(zhuǎn)換為json對象
var dataObj=eval("("+data+")");
為什么要 eval這里要添加 ("("+data+")"); 呢?
原因在于:eval本身的問題。 由于json是以”{}”的方式來開始以及結(jié)束的,在JS中,它會被當成一個語句塊來處理,所以必須強制性的將它轉(zhuǎn)換成一種表達式。
加上圓括號的目的是迫使eval函數(shù)在處理JavaScript代碼的時候強制將括號內(nèi)的表達式(expression)轉(zhuǎn)化為對象,而不是作為語句(statement)來執(zhí)行。舉一個例子,例如對象字面量{},如若不加外層的括號,那么eval會將大括號識別為JavaScript代碼塊的開始和結(jié)束標記,那么{}將會被認為是執(zhí)行了一句空語句。所以下面兩個執(zhí)行結(jié)果是不同的:
// return undefined
alert(eval("{}");
// return object[Object]
alert(eval("({})");
對于這種寫法,在JS中,可以到處看到。如: (function()) {}(); 做閉包操作時等。
//輸出root的子對象數(shù)量
alert(dataObj.root.length);
$.each(dataObj.root,fucntion(idx,item){
if(idx==0){
return true;
}
//輸出每個root子對象的名稱和值
alert("name:"+item.name+",value:"+item.value);
});
對于一般的js生成json對象,只需要將$.each()方法替換為for語句即可,其他不變。
服務器返回的JSON字符串
對于服務器返回的JSON字符串,如果jquery異步請求將type(一般為這個配置屬性)設為“json”,或者利 用$.getJSON()方法獲得服務器返回,那么就不需要eval()方法了,因為這時候得到的結(jié)果已經(jīng)是json對象了,只需直接調(diào)用該對象即可,這里以$.getJSON方法為例說明數(shù)據(jù)處理方法:
$.getJSON("http://www.phpzixue.cn/",{param:"gaoyusi"},function(data){
//此處返回的data已經(jīng)是json對象
//以下其他操作同第一種情況
$.each(data.root,function(idx,item){
if(idx==0){
//同countinue,返回false同break
return true;
}
alert("name:"+item.name+",value:"+item.value);
});
});
這里特別需要注意的是方式1中的eval()方法是動態(tài)執(zhí)行其中字符串(可能是js腳本)的,這樣很容易會造成系統(tǒng)的安全問題。所以可以采用一些規(guī)避了eval()的第三方客戶端腳本庫,比如JSON in JavaScript就提供了一個不超過3k的腳本庫。
第二種解析方式就是使用Function對象來完成,它的典型應用就是在JQuery中的AJAX方法下的success等對于返回數(shù)據(jù)data的解析。
var json='{"name":"CJ","age":18}';
data =(new Function("","return "+json))();
此時的data就是一個會解析成一個json對象了。
使用JSON
JSON也就是JavaScript Object Notation,是一個描述數(shù)據(jù)的輕量級語法。JSON的優(yōu)雅是因為它是JavaScript語言的一個子集。接下來你將看到它為什么如此重要。首先,來比較一下JSON和XML語法。
JSON和XML都使用結(jié)構(gòu)化方法描述數(shù)據(jù)。例如一個地址簿應用程序可以提供用來產(chǎn)生XML格式的地址卡的web服務:
<?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有結(jié)構(gòu)化的嵌套數(shù)據(jù)元素,這一點和XML相似。JSON也是基于文本的,XML也是如此。兩者都使用Unicode。 JSON和XML都很容易閱讀。主觀上,JSON更清晰,冗余更少。JSON WEB站點嚴格地描述了JSON語法,目前就是這樣的。它確實是一個簡單的小語言! XML確實適合標記文檔,但是JSON是數(shù)據(jù)交互的理想格式。每個JSON文檔描述了一個這樣一個對象,該對象包含有:嵌套對象、數(shù)組、字符串、數(shù)字、布 爾值或空值。
在這些地址卡例子代碼中,JSON版本是更輕量級的,只占用了682字節(jié)的空間,而XML版本需要744字節(jié)空間。盡管這不是一個可觀的節(jié)省。而實際的好處則來自解析過程。
XML對比JSON:地位喪失
通過使用XMLHttpRequest對象,可以從你的基于AJAX的應用程序取得XML和JSON文件。典型的,交互代碼如下:
var req = new XMLHttpRequest();
req.open("GET", "http://localhost/addr?cardID=32", /*async*/true);
req.onreadystatechange = myHandler;
req.send(/*no params*/null);
作為WEB服務器響應,你提供的處理器函數(shù)(myHandler函數(shù))被多次調(diào)用,為你提供提前終止事務,更新進度條等機會。通常的,只有在web請求完成以后才起作用:那時,你就可以使用返回的數(shù)據(jù)了。
為了處理XML版本的地址卡數(shù)據(jù),myHandler的代碼如下:
function myHandler() {
if (req.readyState == 4 /*complete*/) {
// Update address field in a form with first street address
var addrField = document.getElementById('addr');
var root = req.responseXML;
var addrsElem = root.getElementsByTagName('addresses')[0];
var firstAddr = addrsElem.getElementsByTagName('address')[0];
var addrText = fistAddr.firstChild;
var addrValue = addrText.nodeValue;
addrField.value = addrValue;
}
}
值得注意的是你不必解析XML文檔:XMLHttpRequest對象自動地解析了,并使responseXML中的DOM樹可用。通過使用 responseXML屬性,可以調(diào)用getElementsByTagName方法查找文檔的地址部分,你還可以使用第一個去找到它。然后,可以再次調(diào) 用getElementsByTagName在地址部分查找第一個地址元素。這就取得了文檔的第一個DOM子節(jié)點,就是一個文本節(jié)點,并取得節(jié)點的值,這 就是你想要的街道地址。最后,可以在表單域中顯示結(jié)果。
確實不是一個簡單的工作,現(xiàn)在,使用JSON再試一下:
function myHandler() {
if (req.readyState == 4 /*complete*/) {
var addrField = document.getElementById('addr');
var card = eval('(' + req.responseText + ')');
addrField.value = card.addresses[0].value;
}
}
你所做的第一件事情就是解析JSON響應。但是,因為JSON是JavaScript的一個子集,你可以使用JavaScript自己的編譯器來解析它, 通過調(diào)用eval函數(shù)。解析JSON僅需要一行!此外,操縱JSON中的對象就像操縱其他JavaScript對象一樣。這顯然要比通過DOM樹來操縱簡 單,例如:
card.addresses[0].value 是第一個街道地址, "1234 Main Stb &"
card.addresses[0].type 是地址類型, "work"
card.addresses[1] 是家庭地址對象
card.fullname 是card的名稱, "Sean Kelly"
如果更仔細觀察,你可能會發(fā)現(xiàn)XML格式中文檔至少有一個跟元素,card。這在JSON里是不存在的,為什么? 大概就是,如果你正在開發(fā)JavaScript來訪問Web服務,你已經(jīng)知道你想要得到的。然而,你可以在JSON中這么使用:
{"card": {"fullname": ...}}
使用這個技術(shù),你的JSON文件總是以一個帶有單一命名屬性的對象開始,該屬性標識了對象的種類。
JSON是快速可靠的嗎?
JSON提供輕量的小文檔,并且JSON在JavaScript更容易使用。XMLHttpRequest自動為你解析了XML文檔,而你還要手工解析 JSON文件,但是解析JSON比解析XML更慢么?作者通過幾千次的反復測試,使用XMLHttpRequest解析XML和解析JSON,結(jié)果是解析 JSON比XML要快10倍!當把AJAX當作桌面應用看待時,速度是最重要的因素,很明顯,JSON更優(yōu)秀。
當然,你不能總是控制服務器端來為AJAX程序產(chǎn)生數(shù)據(jù)。你還可以使用第三方服務器代替服務器提供XML格式的輸出。并且,如果服務器恰好提供JSON,你可以確定你真的想使用它嗎?
代碼中值得注意的是,你將響應文本直接傳入到eval中。如果你控制著服務器,就可以這么做。如果不是,一個惡意服務器可以使你的瀏覽器執(zhí)行危險操作。在這樣的情況下,你最好使用寫在JavaScript中的代碼來解析JSON。幸運地,這已經(jīng)有了。
說到解析,Python愛好者可能注意到JSON不只是JavaScript的子集,它還是Python的一個子集。你可以在Python中直接執(zhí)行JSON,或者使用安全JSON解析代替。JSON.org網(wǎng)站列舉了許多常用JSON解析器。
服務器端的JSON
到現(xiàn)在為止,你或許將焦點注意在運行在客戶瀏覽器中的基于AJAX的web應用程序使用JSON。自然地,首先,JSON格式的數(shù)據(jù)必須在服務器端產(chǎn)生。 幸運地是,創(chuàng)建JSON或?qū)⑵渌嬖诘臄?shù)據(jù)轉(zhuǎn)換成JSON是相當簡單的。一些WEB應用程序框架,例如TurboGears,自動包括對JSON輸出的支 持。
此外商業(yè)WEB服務提供商也注意到了JSON。Yahoo最近創(chuàng)建了許多基于JSON的web服務。Yahoo的多種搜索服務,履行計 劃,del.icio.us,還有高速公路交通服務也都支持JSON輸出。毫無疑問,其他主要WEB服務提供商也將加入到對JSON的支持中。
更多建議: