你不知道的 JSON API

原文連接:宿雪冷音node

JSON

歷史

道格拉斯·克羅克福德(沒錯,就是那個提出原型式繼承的人)在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''
  • valueroot
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)
複製代碼

節點訪問函數必須指定其返回值:

  • 返回value,不作任何修改。
  • 返回一個不一樣值,替換當前節點。
  • 返回undefined,此時當前節點被刪除。
//不指定返回值,根節點直接被刪除
function nodeVisitor(key, value) {
    console.log(this, key, value)
}
JSON.stringify({x:1},nodeVisitor) // undefined
複製代碼

利用節點訪問函數,你能夠檢查JSON方法是如何遍歷數據的。

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}
複製代碼
相關文章
相關標籤/搜索