【疾速入門系列】深入淺出JSON

媒介

JSON(JavaScript Object Notation,JavaScript對象示意法)是JavaScript的一個嚴厲的子集,利用了JavaScript中的一些情勢來示意構造化數據。
JSON是一種數據花樣,不是一種編程言語,雖然具有雷同的語法花樣,但JSON並不從屬於JavaScript,也並不只要JavaScript才運用JSON,許多編程言語都有針對JSON的剖析器和序列化器。

一、JSON

JSON的語法能夠示意三種範例的值:簡樸值、對象和數組。

簡樸值

最簡樸的JSON數據情勢就是簡樸值,如:
JSON示意數值7的體式格局:

7

JSON示意字符串的體式格局:

"Hello Miyang!"

JavaScript字符串與JSON字符串最大的區分在於,JSON字符串必需運用雙引號
布爾值和null也是有效的JSON情勢。

對象

我們來對照一下JSON中的對象和JavaScript字面量:
JavaScript字面量:

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

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

在JSON中的對象請求必需給屬性加引號:

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

比擬二者,JSON沒有聲明變量,其次,末端也沒有分號,最主要的一點,對象的屬性必需加雙引號。
在實際運用中,我們常常會碰到如許的JSON數據:

{
    "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"]        
    }
]

二、剖析與序列化

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章

    原文作者:Miyang
    原文地址: https://segmentfault.com/a/1190000014834511
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞