原文連接:宿雪冷音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
它會影響輸出格式,能夠插入新行並經過數組和對象的嵌套增長縮進:函數
若是是一個數字, 則在字符串化時每一級別會比上一級別縮進多這個數字值的空格,小於0解釋成0,大於10解釋成10:ui
JSON.stringify({ foo: 1, bar: {foo: 1, bar: 1} }, null, 4)
//輸出
"{
"foo": 1,
"bar": {
"foo": 1,
"bar": 1
}
}"
複製代碼
若是是一個字符串,則每一級別會比上一級別多一個用該字符串造成的縮進(或該字符串的前十個字符):this
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 方法後的返回值會被序列化:spa
var x = {
toJSON: function (){
return {x:1}
}
}
JSON.stringify(x) // "{"x":1}"
JSON.stringify({a: x}) // "{"a":{"x":1}}"
複製代碼
toJSON()
方法能夠接收一個位置參數key
,它始終是字符串,有如下值:code
""
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?)
。對象
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}
複製代碼