JSON只是一種字符串數據格式,使用它的不單單是Javascript。git
JSON能夠表示三種類型的值:簡單值、對象、數組github
如下是JSON能夠辨識的簡單值例子:web
5 "Hello World!" false null
*注意:編程
在Javascript中,咱們能夠用對象字面量的方式建立一個對象:數組
var person = { name: "Sue", age: "18" }
但JSON要求給屬性加雙引號,上述對象轉換成合法的JSON字符串格式:瀏覽器
{ "name": "Sue", "age": "18" }
*注意:服務器
在Javascript中,咱們能夠建立一個以下數組:函數
var names = ["Sue", "Jane", "Ben"]
上述數組轉換成合法的JSON字符串格式:this
["Sue", "Jane", "Ben"]
咱們能夠將數組、簡單值、對象嵌套使用,建立更加複雜的JSON字符串,好比:prototype
{ "teachers": [ { "name": "Sue", "age": 18, "students": [1, 45, 60]}, { "name": "Ben", "age": 25, "students": [2, 31, 40]} ], "students": [ { "id": 1, "name": "Jane"}, { "id": 2, "name": "Lee"} ] }
在JSON以前,web傳輸格式化數據都是使用XML,Javascript要想拿到XML中的數據,要先將其轉換成DOM,然後從中提取數據,相比之下,JSON就顯得很是簡單。
早期解析JSON通常使用eval()
,好比:
eval({"name": "Sue"}) {name: "Sue"}
但這種方式存在風險,由於服務器返回的數據頗有可能存在惡意代碼,只要被解析成合法的Javascript語法,就會被執行,好比:
eval("alert('Sue')")
所以不建議使用eval()
來解析JSON字符串。
早期瀏覽器中,可使用https://github.com/douglascro...。
在IE 8+、 Firefox 3.5+、 Safari 4+、 Chrome、Opera 10.5+中,ECMAScript定義了全局對象JSON。
用於把Javascript對象序列化爲JSON字符串。
*注意:
undefined
的屬性會被忽略舉個例子:
function Person(name, secret) { this.name = name; this.secret = secret; this.makeFriends = function() { return this.secret; } } Person.prototype.sayHi = function() { return this.name; } var me = new Person("Sue", undefined) me.makeFriends() // undefined me.sayHi() // "Sue" var meJSON = JSON.stringify(me); // "{"name":"Sue"}"
上述例子中,咱們建立了一個Person
實例me
,其中secret
屬性爲undefined
,包含makeFriends
方法和一個原型成員sayHi
,這些都沒有被添加到生成的JSON字符串中。
這個方法可使咱們沒必要在意Javascript語法與JSON語法的差別,儘管建立合法的Javascript對象。
用於把JSON字符串序列化爲Javascript值。
var meCopy = JSON.parse(meJSON) // {name: "Sue"}
*注意:me
與meCopy
是兩個獨立的對象,實際編程中,可使用stringify
parse
實現對象的拷貝。
JSON.stringify()
的第一個參數是要序列化的對象,後面還能夠加兩個參數,分別是過濾器和選項。
過濾器能夠是數組,也能夠是函數,若是是數組,JSON.stringify()
的結果中將保留數組中的屬性,好比:
function Person(name, age, secret) { this.name = name; this.age = age; this.secret = secret; } var me = new Person("Sue", 18, "none"); var meJSON = JSON.stringify(me, ["name", "age"]) meJSON // "{"name":"Sue","age":18}"
若是過濾器是一個函數,會給這個函數傳入兩個參數,分別是屬性名和屬性值,根據須要返回要添加到JSON中的屬性值,若是爲undefined
,會移除該屬性,好比:
var me = new Person("sue", 25, ["girl", "1024", "Beauty"]) function process(key, value) { switch(key) { case "name": return value.charAt(0).toUpperCase() + value.slice(1); case "age": return 18; case "secret": return undefined; default: return value; } } var meJSON = JSON.stringify(me, process) meJSON // "{"name":"Sue","age":18}"
第三個參數用於控制結果中的縮進和空白符,若是這個參數是一個數值,那麼它表示每一個級別縮進的空格數,好比:
var meJSON = JSON.stringify(me, process, 4) undefined meJSON "{ "name": "Sue", "age": 18 }"
*注意:
若是第三個參數是一個字符串,那麼將使用這個字符串做爲縮進,這個字符串能夠是製表符或其餘任意字符,若是超過10位,則僅前10位有效,好比:
var meJSON = JSON.stringify(me, process, "\t") meJSON "{ "name": "Sue", "age": 18 }"
var meJSON = JSON.stringify(me, process, "****") meJSON "{ ****"name": "Sue", ****"age": 18 }"
當須要爲某種對象添加自定義的序列化方法時,能夠給對象定義toJSON()
方法,好比:
Person.prototype.toJSON = function() { return this.name; } var me = new Person("sue", 25, ["girl", "1024", "Beauty"]) JSON.stringify(me, process, "\t") // ""sue""
上述例子中,咱們在Person
的原型中添加了toJSON
方法,發現調用JSON.stringify
時,只序列化了name
屬性。
序列化的內部順序以下:
No. 1 若是存在toJSON()
,並且它能返回有效的值,則調用它,不然,返回對象自己
No. 2 若是提供了過濾器參數,則基於第一步返回的值調用過濾器
No. 3 序列化第二步的返回值
No. 4 若是提供了縮進,則格式化第三步的返回值
JSON.parse()
能夠接收第二個參數,這個參數是一個還原函數,將在每一個鍵值對上調用,這個函數接收兩個參數,分別是鍵和值,返回處理過的值,好比:
var birth = new Date(1993, 10, 24) JSON.stringify(birth) // ""1993-11-23T16:00:00.000Z"" var birthJSON = JSON.stringify(birth) var birthCopy = JSON.parse(birthJSON, function(key, value) { return new Date(value) }) birthCopy.getFullYear() // 1993