煦涵說JSON

JSON(Javascript Object Notaion, javascript 對象表示法), 是一種數據交換格式,可以在服務器端交換數據, 2001年由Douglas Crockford提出,目的是取代繁瑣笨重的XML格式。javascript

JSON 數據格式的優勢:java

  • 與語言無關的文本數據格式
  • 輕量、簡單、易維護
  • 是javascript編程語言的一個子集(Standard ECMA-262 3rd Edition - December 1999), 符合javascript 語言語法,可使用javascript提供的方法直接解析處理

JSON 創建在兩種數據結構上:git

  • 鍵 / 值對:各類語言中能夠爲 字符串、對象、數組或者哈希表
  • 有序列表(值):各類語言中實現爲數組、向量、列表或者序列

JSON的基本語法:

  • JSON 對象
{
    "key": "value"
}
  • JSON 數組
["value", "value", "value"]
  • value 可取值
  1. 能夠是 String(必須使用雙引號包裹)、Number、Boolean、null、Object、Array, 這些形式能夠嵌套,value值不能是八進制、十六進制(0xF0F)、undefined、function、日期對象,看下面示例:

合格的 JSON 格式:github

{ 
    "name": "煦涵", 
    "name": null, 
    "male": true, 
    "age": 23
}

{ 
    "brother": ["煦涵1", "煦涵2"]
}

{ 
    "brother": {
        "煦涵1": {
            "age": 32
        },
        "煦涵2": {
            "age": 30
        }
    }
}

[{
    "name": "煦涵"
    "age": 30
},{
    "name": "張三"
    "age": 27
}]

不合格的 JSON 格式:正則表達式

// key 必須用雙引號包裹,value 若是是字符串必須用雙引號包裹

{ 'name': "煦涵" } 
[1, 2, 3, 4, oxFOF] 
{ 'name': undefined } 
{ 
    'name': function() { 
        return "煦涵"
    } 
}
{ 'name': new Date() }

若是value的一個String(雙引號包圍)內包含 \"\\\/\b\f\n\r\t\u001f 須要使用反斜槓
若是value的一個Number,不能使用八進制和十六進制數值
PS: value對空格沒有限制要求編程

JSON 對象

聊完 JSON 下面咱們來聊聊 JSON 對象,javascript 在 ES5中新增了 JSON 對象,用來處理 JSON 文本數據,實現字符串與 JSON 對象間的相互轉換,JSON.stringify ( value [ , replacer [ , space ] ] )JSON.parse ( text [ , reviver ] ), 前者是把 JSON 對象轉換爲 JSON 字符串,後者的把 JSON 字符串解析爲 JSON 對象,下面來詳細看看這個兩個方法。json

JSON.stringify ( value [ , replacer [ , space ] ] )

  1. 第一個參數: Value 必須項,能夠是 Object, Array, String, Boolean, Number, Null.看幾個例子:
JSON.stringify({
    "name": "煦涵",
    "age" : 28,
    "male" : true,
    "brother": [1, 2, 3],
    "parent": {
        "father" : {
            "name": "name"
        },
        "mother": {
            "name": "name"
        }
    },
    "other": null
})

// result
"{"name":"煦涵","age":28,"male":true,"brother":["B1","B2","B3"],"parent":{"father":{"name":"name"},"mother":{"name":"name"}},"other":null}"

當待轉換值不是 JSON 的基本類型時:數組

  • 原始對象 item 值是 undefined、函數或 XML 對象,值會被過濾;
  • 數組 item 是 undefined、函數或 XML 對象,值會被轉成 null;
  • 正則對象會被轉換成空對象;
  • 對象的不可遍歷屬性會被忽略;
  • 八進制和十六進制會被轉換成十進制;
  • 特殊字符須要轉義成反斜槓
JSON.stringify({
    "name": undefined,
    "age" : function() {return 28},
    "male" : /male/g,
    "brother": [undefined, function() {return abc}, "B3", 0xFOF],
    "parent": {
        "father" : {
            "name": undefined
        },
        "mother": {
            "name": "name"
        }
    },
    "other": null
})

// result: 正則被轉出了空對象,undefined, function 被忽略或者轉成 null

"{"male":{},"brother":[null,null,"B3", 3855],"parent":{"father":{},"mother":{"name":"name"}},"other":null}"

/* 不可遍歷屬性 */
var demo = {};
Object.defineProperties(demo, {
    "name": {
        value: "煦涵",
        enumerable: false
    },
    "age": {
        value: 28,
        enumerable: true
    }
})
JSON.stringify(demo);

// enumerable: 當且僅當該屬性的 enumerable 爲 true 時,該屬性纔可以出如今對象的枚舉屬性中,
// result: name 屬性會被過濾
"{"age":28}"

/* 特殊字符處理-01 */
JSON.stringify({
    "special01": "回車 \r,換行 \n,退格 \b,換頁 \f,Tab \t",
    "special02": "雙引號 \",單引號 ', 斜槓 \/, 反斜槓 \\",
    "special03": "unicdoe字符 \u001f"
})

// result
'{"special01":"回車 \r,換行 \n,退格 \b,換頁 \f,Tab \t","special02":"雙引號 \",單引號 ', 斜槓 /, 反斜槓 \\","special03":"unicdoe字符 \u001f"}'

/* 特殊字符處理-02 */
var demo = {}
demo.special01 = '回車 \r,換行 \n,退格 \b,換頁 \f,Tab \t';
demo.special02 = '雙引號 ",斜槓 /, 反斜槓\,end ';
demo.special03 = 'unicdoe字符 \u001f';
JSON.stringify(demo);

// result, 雙引號被轉義了,反斜槓被忽略了
'{"special01":"回車 \r,換行 \n,退格 \b,換頁 \f,Tab \t","special02":"雙引號 \",斜槓 /, 反斜槓,end ","special03":"unicdoe字符 \u001f"}'
  1. 第二個參數:replacer可選項,能夠是 array or function
  • 當replacer 是數組時,對第一個參數 value進行過濾,key 不在數組裏的不會輸出,這裏須要注意的是,當第一個參數爲Object時纔有效,若是爲Array,無效,看下面例子:
  • 當replacer 是函數時,遞歸遍歷全部的鍵,能夠對對象進行format and replace 等操做
/* replacer 爲數組 */
JSON.stringify({
    "0": "安徽省",
    "1": "蚌埠市",
    "2": "固鎮縣"
}, [0,1])
// result:
'{"0":"安徽省","1":"蚌埠市"}'

JSON.stringify([
    "安徽省",
    "蚌埠市",
    "固鎮縣"
], [0,1])

// result
'["安徽省","蚌埠市","固鎮縣"]'


/* replacer 爲函數 */
JSON.stringify({
    "0": "安徽省",
    "1": "蚌埠市",
    "2": "固鎮縣"
}, function(key, value) {
    // key: '', value: {0: "安徽省", 1: "蚌埠市", 2: "固鎮縣"}
    console.log(key, value);
    return value[0] + value[1] + value[2];
})
// result
""安徽省蚌埠市固鎮縣""
  1. 第三個參數:space 可選項,用於增長format字符的可讀性,可取值 Number, String, 但長度不超過10個字符
JSON.stringify({"name": "煦涵", "age": 28, "male": true, "other": null}, '', 4)

// result 
"{
    "name": "煦涵",
    "age": 28,
    "male": true,
    "other": null
}"

JSON.stringify({"level1": {"level2": {"level3": {"name": "煦涵"} } } }, '', '|---')

// result: 展現屬性結構很直觀
"{
|---"level1": {
|---|---"level2": {
|---|---|---"level3": {
|---|---|---|---"name": "煦涵"
|---|---|---}
|---|---}
|---}
}"
  1. 特殊狀況
    還記得上面的幾種狀況吧,當對象不是原始對象時,處理方式有所不一樣,好比正則表達式時,會返回空對象,日期對象時返回日期字符串;參看文檔是,JSON.stringify發現參數對象有toJSON方法,就直接使用這個方法的返回值做爲參數,而忽略原對象的其餘參數。
JSON.stringify({
    "name": "煦涵",
    "age": 28,
    "toJSON": function() {
        return this.name + '年齡是' + this.age + '歲'
    }
})
// result:
""煦涵年齡是28歲""

/* 日期對象Date原型上包含toJSON 方法,`Date.prototype.toJSON ( key )` */
var date = new Date();
date.toJSON();
JSON.stringify(date);

/* RegExp 對象 JSON.stringify 默認會把正則轉換成空對象,咱們可使用toJSON, 把正則表達式轉換成字符串 */
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/abc/g)
// result
""/abc/g""

JSON.parse ( text [ , reviver ] )

JSON.parse爲 JSON.stringify的逆運算,轉換時 text 必須符合JSON的語法格式, 否則會報錯,reviver 參數 和 JSON.stringify 的參數 replacer相似, 可是遍歷順序和replacer相反。服務器

JSON.parse('{"name":"煦涵","age":28,"male":true,"brother":["B1","B2","B3"],"parent":{"father":{"name":"name"},"mother":{"name":"name"}},"other":null}' )

/* result:
{
    "name": "煦涵",
    "age" : 28,
    "male" : true,
    "brother": ["B1", "B2", "B3"],
    "parent": {
        "father" : {
            "name": "name"
        },
        "mother": {
            "name": "name"
        }
    },
    "other": null
}
*/

JSON.parse('{"level1": {"level2": {"name": "煦涵"} } }', function(key, value) {
    // level2 Object {name: "煦涵"}
    // level1 Object {level2: Object}
    // Object {level1: Object}
    console.log(key, value);
    return value;
})

// result
{"level1":{"level2":{"name":"煦涵"}}}

參考文檔:

http://www.ecma-international.org/ecma-262/5.1/#sec-15.12
https://github.com/douglascrockford/JSON-js/blob/master/json2.js
http://www.json.org/微信

感謝您的閱讀

--eof--

做者[煦涵]
2017年04月30日

下面是「FED實驗室」的微信公衆號二維碼,歡迎長按、掃描關注:
關注FED實驗室

相關文章
相關標籤/搜索