原文連接:宿雪冷音node
道格拉斯·克羅克福德(沒錯,就是那個提出原型式繼承的人)在2001年發現了 JSON 。道格拉斯自稱發現,而不是發明,是由於它原本就存在。實際上,早在1996年,就已經出現了 JSON 的雛形。
JSON 是一種語法,用來序列化對象、數組、數值、字符串、布爾值和 null
。它基於 JavaScript 語法,它的語法是 JavaScript 表達式語法的一個子集。
它須要遵循下面兩個原則:算法
'obj'
)JSON.stringify()
使用方法爲JSON.stringify(value, replacer?, space?)
數組
replacer
用於轉換前替換參數value
。具體以下:bash
//序列化時,碰到數值,則乘以2 function replacer(key, value){ if(typeof value === 'number'){ value = 2 * value } return value } //調用 JSON.stringify({ a: 5, b: [2, 3] }, replacer) //結果 "{"a":10,"b":[4,6]}" 複製代碼
JSON.stringify({ foo: 1, bar: {foo: 1, bar: 1} }, ['bar']) //結果 "{"bar":{"bar":1}" 複製代碼
//對數組來講是無效的 JSON.stringify([2, 4], ['0']) //結果 "[2,4]" 複製代碼
space
它會影響輸出格式,能夠插入新行並經過數組和對象的嵌套增長縮進:markdown
若是是一個數字, 則在字符串化時每一級別會比上一級別縮進多這個數字值的空格,小於0解釋成0,大於10解釋成10:函數
JSON.stringify({ foo: 1, bar: {foo: 1, bar: 1} }, null, 4)
//輸出
"{
"foo": 1,
"bar": {
"foo": 1,
"bar": 1
}
}"
複製代碼
若是是一個字符串,則每一級別會比上一級別多一個用該字符串造成的縮進(或該字符串的前十個字符):oop
JSON.stringify({ foo: 1, bar: {foo: 1, bar: 1} }, null, "----") //輸出 "{ ----"foo": 1, ----"bar": { --------"foo": 1, --------"bar": 1 ----} }" 複製代碼
JSON.stringify
忽略的數據var obj = Object.defineProperty({}, 'foo', {enumerable: false, value: 7}) JSON.stringify(obj) // "{}" 複製代碼
null
之外的任何值。如函數,Symbol值,undefined
等,將返回undefined
。若是屬性值是這些值,該屬性直接被忽略,在數組中被解析成null
:JSON.stringify(function (){}) // undefined JSON.stringify({foo: function (){} }) // "{}" JSON.stringify([function (){}]) // "[null]" 複製代碼
toJSON(key)
方法若是一個被序列化的對象擁有 toJSON 方法,那麼該 toJSON 方法就會覆蓋該對象默認的序列化行爲:不是那個對象被序列化,而是調用 toJSON 方法後的返回值會被序列化:this
var x = { toJSON: function (){ return {x:1} } } JSON.stringify(x) // "{"x":1}" JSON.stringify({a: x}) // "{"a":{"x":1}}" 複製代碼
toJSON()
方法能夠接收一個位置參數key
,它始終是字符串,有如下值:spa
""
var x = { toJSON: function (key){ console.log(key) return 1 } } JSON.stringify(x) // 打印 "" JSON.stringify({a: x}) // 打印 "a" JSON.stringify([x]) // 打印 "0" 複製代碼
JSON.parse()
使用方法JSON.parse(text, reviver?)
。code
JSON.parse(""string"") // Uncaught SyntaxError: missing ) after argument list JSON.parse('"string"') // "string" JSON.parse('1') // 1 JSON.parse('[1]') // [1] JSON.parse('[1,]') // Uncaught SyntaxError。不容許用逗號做爲結尾 JSON.parse('{"x":1}') // {x:1} 複製代碼
""stirng""
是不被js支持的,儘管雖然是標準的JSON字符串。你可使用'"string"'
代替。若是確實須要這樣的形式,可使用JSON.stringify("")
revier
參數它是一個節點訪問函數。它能夠用來轉換解析後的數據:
//轉換JSON字符串中的日期 function dateReviver(key, value){ if (typeof value === 'string') { var x = Date.parse(value) if (!isNaN(x)) { return new Date(x) } } return value } var str = '{ "name": "suxue", "date": "2019-04-21T22:00:00.00z"}' JSON.parse(str, dateReviver) // {name: "suxue", date: Mon Apr 22 2019 06:00:00 GMT+0800 (中國標準時間)} 複製代碼
JSON.parse()
和JSON.stringify()
均可以傳入一個函數轉換數據:
JSON.stringify()
能夠在轉換成JSON前改變數據。JSON.parse()
解析JSON,並能夠後處理生成的結果數據。節點訪問函數結構以下:
function nodeVisitor(key, value) // this 指向當前節點的父元素 複製代碼
key
值和toJSON()
接收的key
是同樣的。 根節點root
是不存在父元素的。當root
被訪問時,一個僞父元素被建立,此時的參數值是:
this
指向 {'': root}
,root 指根節點key
是 ''
value
是 root
function nodeVisitor(key, value) { console.log(this, key, value) return value } //第一次 this: {"":{x:1}}, key:"", value:{x:1} // 第二次 this: {x:1}, key : "x", value: 1 JSON.stringify({x:1},nodeVisitor) // 第一次:this: {"":{x:1}} key:"" value:{x:1} // 第二次:this:{a: 1} key: "x" value :{a:1} // ... JSON.stringify({x:{a:1}},nodeVisitor) 複製代碼
節點訪問函數必須指定其返回值:
undefined
,此時當前節點被刪除。//不指定返回值,根節點直接被刪除 function nodeVisitor(key, value) { console.log(this, key, value) } JSON.stringify({x:1},nodeVisitor) // undefined 複製代碼
利用節點訪問函數,你能夠檢查JSON方法是如何遍歷數據的。
JSON.stringify()
採用前序遍歷算法(父元素先於子元素),先訪問特殊的根節點。
JSON.stringify({x:1},nodeVisitor)// 看value值順序 {x:1} => 1 JSON.stringify({x:{a:1}},nodeVisitor)// {x:{a:1}} => {a:1} => 1 複製代碼
JSON.parse()
採用的後序遍歷算法(子元素先於父元素),葉節點先被訪問。
JSON.parse('{"x":1}', nodeVisitor) // 看value值順序 1 => {x:1} JSON.parse('{"x":{"a":1}}', nodeVisitor) // 1 => {a:1} => {x:{a:1} 複製代碼