介紹
我們知道AJAX技術能夠使得每一次請求更加迅捷,對於每一次請求返回的不是整個頁面,也僅僅是所需要返回的數據。通常AJAX通過返回XML格式的數據,然后再通過客戶端復雜的JavaScript腳本解析和渲染這些XML格式的數據。
JSON(讀Jason)是為了能夠使得數據格式成為一種標准,更簡單的被JavaScript解析。
優點
1、輕量級的數據交換格式
2、人們讀寫更加容易
3、易於機器的解析和生成
4、能夠通過JavaScript中eval()函數解析JSON
5、JSON支持多語言。包括:ActionScript, C, C#, ColdFusion, E, Java, JavaScript, ML, Objective CAML, Perl, PHP, Python, Rebol, Ruby, and Lua.
語法
JSON語法是一種用於傳輸和生成數據的協定,很類似於C家族的語言,所以很容易被C家族的語言所解析。
對象:對象包含在{}之間
屬性:采用Key-Value對來表示。屬性之間使用逗號分開。 string : value
數組:數組存放在[]之間 [ elements ]
元素:元素之間用逗號分開
值:值可以是字符串,數字,對象,數組,true,false,null
例子:JSON
[ { name:"Michael", email:"17bity@gmail.com", homepage:"http://www.google.com" }, { name:"John", email:"john@gmail.com", homepage:"http://www.google.com" }, { name:"Peggy", email:"peggy@gmail.com", homepage:"http://www.google.com" } ]
事實上google maps就沒有采用XML傳遞數據,而是采用了JSON方案。
JSON的另外一個優勢是”跨域性”,例如你在網頁里使用
<script type=”text/javascript” src=”http://www.yyy.com/some.js”>
是完全可行的,這就意味着你可以跨域傳遞信息。而使用XMLHttpRequest卻獲取不了跨域的信息,這是Javascript內部的安全性質所限制的。
JSON能完全取代XML嗎?當然不能,原因就在於XML的優勢:通用性。要使服務器端產生語法合格的Javascript代碼並不是很容易做到的,這主要發生在比較龐大的系統,服務器端和客戶端有不同的開發人員。
JSON VS XML
可讀性 JSON和XML的可讀性可謂不相上下,一邊是建議的語法,一邊是規范的標簽形式,很難分出勝負。 可擴展性
XML天生有很好的擴展性,JSON當然也有,沒有什么是XML能擴展,JSON不能的。
編碼難度 XML有豐富的編碼工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的編碼明顯比XML容易許多,即使不借助工具也能寫出JSON的代碼,可是要寫好XML就不太容易了。
解碼難度 XML的解析得考慮子節點父節點,讓人頭昏眼花,而JSON的解析難度幾乎為0。這一點XML輸的真是沒話說。
流行度 XML已經被業界廣泛的使用,而JSON才剛剛開始,但是在Ajax這個特定的領域,未來的發展一定是XML讓位於JSON。到時Ajax應該變成Ajaj (Asynchronous JavaScript and JSON)了。
簡單 JSON 示例
按照最簡單的形式,可以用下面這樣的 JSON 表示名稱/值對:
{ ”firstName”: ”Brett” }
這個示例非常基本,而且實際上比等效的純文本名稱/值對占用更多的空間:
firstName=Brett
但是,當將多個名稱/值對串在一起時,JSON 就會體現出它的價值了.首先,可以創建包含多個名稱/值對的記錄,比如:
{ ”firstName”: ”Brett”, ”lastName”:”McLaughlin”, ”email”: ”tuyile006@163.com” }
從語法方面來看,這與名稱/值對相比並沒有很大的優勢,但是在這種情況下 JSON 更容易使用,而且可讀性更好。例如,它明確地表示以上三個值都是同一記錄的一部分;花括號使這些值有了某種聯系。
值的數組
當需要表示一組值時,JSON 不但能夠提高可讀性,而且可以減少復雜性。例如,假設您希望表示一個人名列表。在XML 中,需要許多開始標記和結束標記;如果使用典型的名稱/值對(就像在本系列前面文章中看到的那種名稱/值對),那么必須建立一種專有的數據格式,或者將鍵名稱修改為 person1-firstName
這樣的形式。
如果使用 JSON,就只需將多個帶花括號的記錄分組在一起:
{ ”programmers”: [ { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" }, { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" }, { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" } ], “authors”: [ { "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" }, { "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" }, { "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" } ], “musicians”: [ { "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" }, { "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" } ] }
這里最值得注意的是,能夠表示多個值,每個值進而包含多個值。但是還應該注意,在不同的主條目(programmers、authors 和 musicians)之間,記錄中實際的名稱/值對可以不一樣。JSON 是完全動態的,允許在 JSON 結構的中間改變表示數據的方式。
在處理 JSON 格式的數據時,沒有需要遵守的預定義的約束。所以,在同樣的數據結構中,可以改變表示數據的方式,甚至可以以不同方式表示同一事物。
在 JavaScript 中使用 JSON
掌握了 JSON 格式之后,在 JavaScript 中使用它就很簡單了。JSON 是 JavaScript 原生格式,這意味着在JavaScript 中處理 JSON 數據不需要任何特殊的 API 或工具包。
將 JSON 數據賦值給變量
例如,可以創建一個新的 JavaScript 變量,然后將 JSON 格式的數據字符串直接賦值給它:
var people = { ”programmers”: [ { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" }, { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" }, { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" } ], ”authors”: [ { "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" }, { "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" }, { "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" } ], ”musicians”: [ { "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" }, { "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" } ] }
這非常簡單;現在 people
包含前面看到的 JSON 格式的數據。但是,這還不夠,因為訪問數據的方式似乎還不明顯。
訪問數據
盡管看起來不明顯,但是上面的長字符串實際上只是一個數組;將這個數組放進 JavaScript 變量之后,就可以很輕松地訪問它。實際上,只需用點號表示法來表示數組元素。所以,要想訪問 programmers 列表的第一個條目的姓氏,只需在 JavaScript 中使用下面這樣的代碼:
- people.programmers[0].lastName;
注意,數組索引是從零開始的。所以,這行代碼首先訪問 people
變量中的數據;然后移動到稱為 programmers
的條目,再移動到第一個記錄([0]
);最后,訪問 lastName
鍵的值。結果是字符串值 “McLaughlin”。
下面是使用同一變量的幾個示例。
people.authors[1].genre // Value is ”fantasy” people.musicians[3].lastName// Undefined. This refers to the fourth entry, and there isn’t one people.programmers.[2].firstName// Value is ”Elliotte”
修改 JSON 數據
正如可以用點號和括號訪問數據,也可以按照同樣的方式輕松地修改數據:
people.musicians[1].lastName = ”Rachmaninov”;
在將字符串轉換為 JavaScript 對象之后,就可以像這樣修改變量中的數據。
轉換回字符串
當然,如果不能輕松地將對象轉換回本文提到的文本格式,那么所有數據修改都沒有太大的價值。在 JavaScript 中這種轉換也很簡單:
String newJSONtext = people.toJSONString();
這樣就行了!現在就獲得了一個可以在任何地方使用的文本字符串,例如,可以將它用作 Ajax 應用程序中的請求字符串。
更重要的是,可以將任何 JavaScript 對象轉換為 JSON 文本。並非只能處理原來用 JSON 字符串賦值的變量。為了對名為 myObject
的對象進行轉換,只需執行相同形式的命令:
String myObjectInJSON = myObject.toJSONString();
這就是 JSON 與本系列討論的其他數據格式之間最大的差異。如果使用 JSON,只需調用一個簡單的函數,就可以獲得經過格式化的數據,可以直接使用了。對於其他數據格式,需要在原始數據和格式化數據之間進行轉換。即使使用Document Object Model 這樣的 API(提供了將自己的數據結構轉換為文本的函數),也需要學習這個 API 並使用API 的對象,而不是使用原生的 JavaScript 對象和語法。
最終結論是,如果要處理大量 JavaScript 對象,那么 JSON 幾乎肯定是一個好選擇,這樣就可以輕松地將數據轉換為可以在請求中發送給服務器端程序的格式。
四種解析Json的方式:
//第一部分 var list1 = [1,3,4]; alert(list1[1]); var list2 = [{"name":"leamiko","xing":"lin"}]; alert(list2[0]["xing"]) alert(list2[0].xing) //第二部分 var value = { ”china”:{ ”hangzhou”:{“item”:”1″}, ”shanghai”:{“item”:”2″}, ”chengdu”:{“item”:”3″} }, ”America”:{ ”aa”:{“item”:”1″}, ”bb”:{“item”:”2″} }, ”Spain”:{ ”dd”:{“item”:”1″}, ”ee”:{“item”:”2″}, ”ff”:{“item”:”3″} } }; for(var countryObj in value) { document.write(countryObj + ”:<br />”) //沒用的for(var cityObj in value.countryObj) for(var cityObj in value[countryObj]) { document.write(‘ ’ + cityObj + ”<br />”); for(var itemObj in value[countryObj][cityObj]) { document.write(“ ”+ itemObj + value[countryObj][cityObj][itemObj] +”<br />”) } } }
說明:
countryObj 為value對象的一個屬性明,value[countryObj] 為value對象的屬性值 這里為一個json對象比如b,value[countryObj][cityObj]為josn對象b的屬性值 它也是一個json對象,於是 value[countryObj][cityObj]["item"]便可以取到json對象暫時成為c的值,或者 value[countryObj][cityObj].item。
總之分清是json還是array這是很關鍵的
//第三部分 var value2 = { ”china”:[ {"name":"hangzhou", "item":"1"}, {"name":"shanghai", "item":"2"}, {"name":"sichuan", "item":"3"} ], ”America”:[ {"name":"aa", "item":"12"}, {"name":"bb", "item":"2"} ], ”Spain”:[ {"name":"cc", "item":"1"}, {"name":"dd", "item":"23"}, {"name":"ee", "item":"3"} ] }; for (var countryObj in value2) { document.write(countryObj + ”:<br />”) for (var cityObj in value2[countryObj]) { //可以用document.write(“ ” + value2[countryObj][cityObj].item + ”<br />”); document.write(cityObj + ” ” + value2[countryObj][cityObj]["name"] + ”<br />” ); } }
說明:
countryObj 為value2對象的屬性名,value2[countryObj] 為value2對象屬性值 在本例中它是一個數組,cityObj 是數組的一個元素,它又是另外一個json對象,於是,value2[countryObj][cityObj]["name"]就訪問到該對象的 name的屬性值,也可以通過 value2[countryObj][cityObj].name 來訪問該屬性值。
//第四部分 var value2 = { ”china”:[ {"name":"hangzhou", "item":"1"}, {"name":"shanghai", "item":"2"}, {"name":"sichuan", "item":"3"} ], ”America”:[ {"name":"aa", "item":"12"}, {"name":"bb", "item":"2"} ], ”Spain”:[ {"name":"cc", "item":"1"}, {"name":"dd", "item":"23"}, {"name":"ee", "item":"3"} ] }; for (var countryObj in value2) { document.write(countryObj + ”:<br />”) //document.write(“ ” + value2[countryObj].length); for (var i = 0;i < value2[countryObj].length; i++) { document.write(“ ” + value2[countryObj][i]["name"] + ”<br />”); } }
說明:
countryObj value2對象的屬性名,value2[countryObj] 屬性值 本例中是一個數組,value2[countryObj].length 數組的長度,value2[countryObj][i]數組的項 == json對象。
value2[countryObj][i]["name"] 取得name的值,也可以用value2[countryObj][i].name 來取得name的值。
將后台程序(如php)發送過來的json數據轉化為javascript的數組或者對象的方法十分簡單,代碼如下:
- // 假設后台發送的json數據為 ’{a:2,b:1}’ 存儲於str中
- var data = eval( ’(‘ + str + ’)' );
然而想將一個javascript對象轉化為json格式的字符串卻並不那么簡單,特別是對象的屬性值遞歸包含一個對象時(如 var obj={a:[2,3],b:{m:[3,4],n:2} } ),那么有沒有什么方法將obj轉化為json格式的字符串呢?
當然你可以自己寫一個函數,遞歸遍歷一個對象並將其轉化為json格式的字符串,對於大部分人來說這有些困難並容易出錯。幸好已經有人做好了這件事情,你只用包含一段javascript代碼即可。
使用方法:
//第四部分 var value2 = { ”china”:[ {"name":"hangzhou", "item":"1"}, {"name":"shanghai", "item":"2"}, {"name":"sichuan", "item":"3"} ], ”America”:[ {"name":"aa", "item":"12"}, {"name":"bb", "item":"2"} ], ”Spain”:[ {"name":"cc", "item":"1"}, {"name":"dd", "item":"23"}, {"name":"ee", "item":"3"} ] }; for (var countryObj in value2) { document.write(countryObj + ”:<br />”) //document.write(“ ” + value2[countryObj].length); for (var i = 0;i < value2[countryObj].length; i++) { document.write(“ ” + value2[countryObj][i]["name"] + ”<br />”); } }
假如有兩個變量,我要將a轉換成字符串,將b轉換成JSON對象:
在Firefox,chrome,opera,safari,ie9,ie8等高級瀏覽器直接可以用JSON對象的stringify()和 parse()方法。JSON.stringify(obj)將JSON轉為字符串。JSON.parse(string)將字符串轉為JSON格式;
上面的轉換可以這么寫:
var a={“name”:”tom”,”sex”:”男”,”age”:”24″}; var b=’{“name”:”Mike”,”sex”:”女”,”age”:”29″}’; var aToStr=JSON.stringify(a); var bToObj=JSON.parse(b); alert(typeof(aToStr)); //string alert(typeof(bToObj)); //object
JSON.stringify()
ie8(兼容模式),ie7和ie6沒有JSON對象,不過http://www.json.org/提供了一個json.js,這樣ie8(兼 容模式),ie7和ie6就可以支持JSON對象以及其stringify()和parse()方法;你可以在https://github.com /douglascrockford/JSON-js上獲取到這個js,一般現在用json2.js。ie8(兼容模式),ie7和ie6可以使用 eval()將字符串轉為JSON對象:
jQuery中也有將字符串轉為JSON格式的方法jQuery.parseJSON( json ),接受一個標准格式的 JSON 字符串,並返回解析后的 JavaScript (JSON)對象。當然如果有興趣可以自己封裝一個jQuery擴展,jQuery.stringifyJSON(obj)將JSON轉為字符串。
JSON.stringify(jsonobj),本來是最簡便的方法,可是存在瀏覽器兼容問題(僅適用於IE8+,Chrome 1+,FF 3+)。下面再介紹一個方法:
var O2String = function (O) { //return JSON.stringify(jsonobj); var S = []; var J = ”"; if (Object.prototype.toString.apply(O) === ’[object Array]‘) { for (var i = 0; i < O.length; i++) S.push(O2String(O[i])); J = ’[' + S.join(',') + ']‘; } else if (Object.prototype.toString.apply(O) === ’[object Date]‘) { J = ”new Date(“ + O.getTime() + ”)”; } else if (Object.prototype.toString.apply(O) === ’[object RegExp]‘ || Object.prototype.toString.apply(O) === ’[object Function]‘) { J = O.toString(); } else if (Object.prototype.toString.apply(O) === ’[object Object]‘) { for (var i in O) { O[i] = typeof (O[i]) == ’string’ ? ’”‘ + O[i] + ’”‘ : (typeof (O[i]) === ’object’ ? O2String(O[i]) : O[i]); S.push(i + ’:' + O[i]); } J = ’{‘ + S.join(‘,’) + ’}'; } return J; };
使用方法也很簡單:
var jsonStr = O2String( [ { "Page": "plan", "Custom": [ { "ItemName": "CustomLabel1", "ItemContent": 1, "IsItem": true, "ItemDate": new Date(1320774905467), "ItemReg": /[\w]*?/gi, ”ItemFunc”: function () { alert(“ItemFunc”); } }, { ”ItemName”: ”CustomLabel1″, ”ItemContent”: 1, ”IsItem”: true, ”ItemDate”: new Date(1320774905467), ”ItemReg”: /[\w]*?/gi, ”ItemFunc”: function () { alert(“ItemFunc”); } } ] }, { ”Page”: ”project”, ”Custom”: [ { "ItemName": "CustomLabel2", "ItemContent": 2, "IsItem": false, "ItemDate": new Date(1320774905467), "ItemReg": /[\w]*?/gi, ”ItemFunc”: function () { alert(“ItemFunc”); } }, { ”ItemName”: ”CustomLabel2″, ”ItemContent”: 2, ”IsItem”: false, ”ItemDate”: new Date(1320774905467), ”ItemReg”: /[\w]*?/gi, ”ItemFunc”: function () { alert(“ItemFunc”); } } ] } ] ); alert(jsonStr); var jsonObj = eval(“(“ + jsonStr + ”)”); alert(jsonObj.length);