【快速入門系列】深刻淺出JSON

前言

JSON(JavaScript Object Notation,JavaScript對象表示法)是JavaScript的一個嚴格的子集,利用了JavaScript中的一些模式來表示結構化數據。
JSON是一種數據格式,不是一種編程語言,雖然具備相同的語法格式,但JSON並不從屬於JavaScript,也並不僅有JavaScript才使用JSON,不少編程語言都有針對JSON的解析器和序列化器。編程

1、JSON

JSON的語法能夠表示三種類型的值:簡單值、對象和數組。json

簡單值

最簡單的JSON數據形式就是簡單值,如:
JSON表示數值7的方式:數組

7

JSON表示字符串的方式:數據結構

"Hello Miyang!"

JavaScript字符串與JSON字符串最大的區別在於,JSON字符串必須使用雙引號
布爾值和null也是有效的JSON形式。編程語言

對象

咱們來對比一下JSON中的對象和JavaScript字面量:
JavaScript字面量:函數

var person = {
    name: "Miyang",
    age: 21
};

this

var person = {
    "name": "Miyang",
    "age": 21
};

在JSON中的對象要求必須給屬性加引號:設計

{
    "name": "Miyang",
    "age": 21
}

相比二者,JSON沒有聲明變量,其次,末尾也沒有分號,最重要的一點,對象的屬性必須加雙引號。
在實際使用中,咱們常常會遇到這樣的JSON數據:code

{
    "name": "Miyang",
    "age": 21,
    "location": {
        "name": "Ping guo yuan",
        "city": "Beijing"
    }
}

雖然該JSON中存在兩個name屬性,但因爲它們分別屬於不一樣的對象,所以沒有問題。同一個對象中絕對不該該出現兩個同名屬性對象

數組

在JSON中,能夠採用與JavaScript相同的語法表示一個數組:

["Miyang", 21, true]

一樣的,JSON數組也沒有變量和分號,數組和對象結合起來,能夠構成較爲複雜的數據集合。

[
    {
        "name": "Miyang",
        "age": 21,
        "hobby": ["HTML", "CSS", "Javascript"]        
    },
    {
        "name": "Miyang",
        "age": 21,
        "hobby": ["HTML", "CSS", "Javascript"]        
    },
    {
        "name": "Miyang",
        "age": 21,
        "hobby": ["HTML", "CSS", "Javascript"]        
    }
]

2、解析與序列化

JSON的流行,更重要的緣由是能夠把JSON數據結構解析爲有用的JavaScript對象,相對於XML數據結構來講優點極爲明顯。如咱們能夠經過如下方法來獲取某個屬性:

person[0].name

JSON對象

早期JSON解析器基本經過JavaScript的eval()函數,可是存在風險,由於可能會執行一些惡意代碼。從ECMAScript5開始,定義了全局對象JSON,能夠更方便的對JSON進行解析與序列化。

JSON.stringify()

該方法能夠將JavaScript對象序列化爲一個JSON字符串,默認狀況下,輸出的字符串不包含任何空格字符或縮進,如:

var json = {
  "name": "Miyang",
  "age": 21
};

console.log(JSON.stringify(json));
// 輸出結果
{"name":"Miyang","age":21}

在序列化JavaScript對象時,全部函數即原型成員都會被有意忽略,不體如今結果中,值爲undefined的任何屬性也會被跳過,如:

var json = {
  "name": "Miyang",
  "age": 21,
  "test": undefined
};

console.log(JSON.stringify(json));
// 輸出結果
{"name":"Miyang","age":21}

JSON.parse()

該方法能夠將JSON字符串轉換爲JSON對象,如:

var jsonTest = '{"name": "Miyang","age": 21,"test": "undefined"}';
console.log(JSON.parse(jsonTest));
// 輸出結果
{ name: 'Miyang', age: 21, test: 'undefined' }

若是傳給JSON.parse()的字符串不是有效的JSON,該方法會拋出錯誤

序列化選項

JSON.stringfiy() 還能夠接受兩個參數,用於指定以不一樣方式序列化JavaScript對象。
第一個參數是過濾器,能夠是一個數組,也能夠是一個函數。
第二個參數是一個選項,表示是否在JSON字符串中保留縮進。

過濾結果

若是過濾器參數是數組,那麼返回的結果就只包含數組中列出的屬性,如:

var json = {
  "name": "Miyang",
  "age": 21
};
console.log(JSON.stringify(json, ["name"]));
// 輸出結果
{"name":"Miyang"}

若是過濾器參數是函數,則該函數能夠接收兩個參數,屬性名和屬性值,隨後根據函數對結果進行過濾,如:

var json = {
  "name": "Miyang",
  "age": 21,
  "hobby": ["HTML", "CSS"]
};
console.log(JSON.stringify(json, function(key, value) {
  switch(key) {
    case "name":
      return value + "!!!";
    case "age":
      return 18;
    case "hobby":
      return undefined;
    default:
      return value;
  }
}));
// 輸出結果
{"name":"Miyang!!!","age":18}

這裏注意,若是函數返回了undefined,那麼相應的屬性會被忽略

字符串縮進

JSON.stringify()的第三個方法用於控制結果中的縮進和空白符,若是該參數是一個數值,則表示每一個縮進的空格數,最大縮進爲10,大於10的值會自動轉換爲10。當傳入了有效縮進參數值,結果字符串就會包含換行符。

var json = {
  "name": "Miyang",
  "age": 21,
  "hobby": ["HTML", "CSS"]
};
console.log(JSON.stringify(json, null, 2));
// 輸出結果
{
  "name": "Miyang",
  "age": 21,
  "hobby": [
    "HTML",
    "CSS"
  ]
}

若是縮進參數是一個字符串,則這個字符串將在JSON字符串在做爲縮進字符,一樣的,長度不能超過10個字符長,不然只顯示前10個字符。

var json = {
  "name": "Miyang",
  "age": 21,
  "hobby": ["HTML", "CSS"]
};
console.log(JSON.stringify(json, null, '-'));
// 輸出結果
{
-"name": "Miyang",
-"age": 21,
-"hobby": [
--"HTML",
--"CSS"
-]
}

toJSON()方法

JSON.stringify()不能知足需求時,能夠給對象定義toJSON()方法,返回其自身的JSON數據格式。

var json = {
  "name": "Miyang",
  "age": 21,
  "address": {
    "city": "Beijing"
  },
  toJSON: function() {
    return this.name;
  }
};
console.log(JSON.stringify(json));
// 輸出結果
"Miyang"

可讓這個方法返回undefined,若是此時包含它的對象嵌入在另外一個對象中,會致使它的值變成null,若是是頂級對象,則返回undefined

var json = {
  "name": "Miyang",
  "age": 21,
  "address": {
    "city": "Beijing"
  },
  toJSON: function() {
    return undefined;
  }
};
console.log(JSON.stringify(json));
// 輸出結果
undefined
var json = {
  "name": "Miyang",
  "age": 21,
  "address": {
    "city": "Beijing",
    toJSON: function() {
      return undefined;
    }
  }
};
console.log(JSON.stringify(json));
// 輸出結果
{"name":"Miyang","age":21}

序列化內部工做順序

咱們須要瞭解一下序列化內部工做順序,假設把一個對象傳入JSON.stringify(),序列化該對象的順序以下:

  1. 若是存在toJSON()方法並且能取得有效值,則調用該方法,不然返回對象自己。
  2. 若是提供了第二個參數,應用這個函數過濾器,傳入的值是第1步返回的值。
  3. 對第2步返回的每一個值進行相應的序列化。
  4. 若是提供了第三個參數,執行相應的格式化。

解析選項

JSON.parse()也能夠接收另外一個參數,該參數是一個函數,對每一個鍵值對進行調用,被稱之爲還原函數。一樣的,它接收兩個參數,一個鍵和一個值,且須要返回一個值。
若是返回undefined,則表示要從結果中刪除相應的鍵,若是返回其餘值,則將該值插入到結果中,在將日期字符串轉換爲Date對象時,常常用到還原函數。

var json = {
  "name": "Miyang",
  "age": 21,
  "address": {
    "city": "Beijing"
  },
  "date": new Date(2011, 11, 1)
};
var jsonText = JSON.stringify(json);

var jsonCopy = JSON.parse(jsonText, function(key, value) {
  if(key === "date") {
    return new Date(value);
  }else {
    return value;
  }
});
console.log(jsonCopy.date.getTime());
// 輸出結果
1322668800000

結束語

JSON是一個輕量級的數據格式,能夠簡化表示複雜數據結構的工做量,瞭解其結構、掌握JavaScript對其的操做方法,能夠更便捷的進行先後臺交互或數據處理。

參考資料:JavaScript高級程序設計(第三版)第20章
相關文章
相關標籤/搜索