[TOC]
## 11.1 語法
.JSON語法可以表示以下三種類型的值:
* 簡單值:使用與JavaScript相同的語法,可以在JSON中表示字符串(雙引)、數值(必須以十進制表示)、布爾值和null(不能使用NaN, Infinity, -Infinity和undefined)。但JSON不支持JavaScript中的特殊值undefined。
* 對象:對象作為一種復雜數據類型,表示的是一組無序的鍵值對。而每個鍵值對中的值可以是簡單值,也可以是復雜數據類型的值。(鍵名必須在雙引號內)
* 數組:數組也是一種復雜數據類型,表示一組有序的值的列表,可以通過數值索引來訪問其中的值。(最后成員不加逗號)
### 11.1.1 簡單值
最簡單的JSON數據形式就是簡單值。
~~~
5
"Hello world"
null
true
false
~~~
上面的都是有效的JSON數據。
### 11.1.2 對象
JSON中的對象與JavaScript中的對象字面量基本一樣,除了JSON中的對象要求**對象的屬性一定要加上雙引號**。
JavaScript中的對象字面量:
~~~
標準形式
var object = {
name: "Nicholas",
age: 29;
};
或
var object = {
"name": "Nicholas",
"age": 29;
};
~~~
JSON中的對象字面量(沒有聲明,對象的屬性必須加雙引號,末尾沒分好):
~~~
{
"name": "Nicholas",
"age": 29;
}
~~~
當然,可以使用嵌套對象:
~~~
{
"name": "Nicholas",
"age": 29,
"school": {
"name" : "Merrimack College",
"location": "North Andover, MA"
}
}
~~~
上面有兩個同名(name)屬性,這是沒問題的,因為它們屬于不同的對象。
**不同對象可以有同名屬性,但同一對象內不能出現同名屬性。**
### 11.1.3 數組
JSON數組采用的是JavaScript中的數組字面量,**也沒有變量和分號**。
~~~
{
//JavaScript:
var values = [25,"hi",true];
//JSON
[25,"hi",true]
}
~~~
**還可以在數組中放對象,對象中放數組。**
## 11.2 解析與序列化
JSON在JavaScript中流行的原因是JSON數據結構可以解析成有用的JavaScript對象。
### 11.2.1 JSON對象
JSON是JavaScript語法的子集,因此eval()函數可以解析、解釋并返回JavaScript對象和數組。
JSON對象有兩個方法:`stringify()和parse()`。
JSON.stringify()把**JavaScript對象序列化為一個JSON字符串**(不包含任何空格字符或縮進)。
注意:在序列化JavaScript對象時,所有函數及原型成員都會被有意忽略,不體現在結果中,而且值為undefined的任何屬性也會被跳過,還有正則對象會被轉成空對象。最終返回來的值為有效的JSON格式。
~~~
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data));
//{"name":"tg","age":1,"books":["Javascript",2],"location":{"name":"gz"}}
~~~
### 11.2.2 序列化選項
JSON.stringify()還接受額外兩個參數,用于指定以不同的方式序列化JavaScript對象。
第二個參數是個過濾器,可以是一個數組,也可以是一個函數;第三個參數是一個選項,表示是否在JSON字符串中保留縮進。
**1. 過濾結果**
當傳入的參數是**數組**時,那么JSON.stringify()的結果中將只包含數組中列出的屬性。
~~~
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data,["name","books"]));
//{"name":"tg","books":["Javascript",2]}
~~~
在上面的例子中,傳給JSON.stringify()的第二個參數是一個數組,其中包含兩個字符串:“name”和“books”,這兩個屬性與將要序列化的對象中的屬性是對應的,因此在返回的結果字符串中,就只會包含這兩個屬性(如上結果)。
第二個參數還可以是**函數**,它接收兩個參數:屬性(鍵)名和屬性值,返回的值就是相應鍵的值(它改變了序列化對象的結果)。
屬性名只能是字符串,而在值并非鍵值對的值時,鍵名可以是空字符串。
~~~
var jsonText = JSON.stringify(data,function(key, value){
if(key == 'books'){
return value.join(',');
}else{
return value;
}
});
console.log(jsonText);
//{"name":"tg","age":1,"books":"Javascript,2","location":{"name":"gz"}}
~~~
在上面的例子中,如果鍵名為"books",就將數組連成一個字符串,否則,返回原值。
注意:如果函數返回了undefined,那么相應的屬性會被忽略。
**2. 字符串縮進**
JSON.stringify()方法還可以接收第三個參數,用于控制結果中的縮進和空白符。如果這個參數是數值,那它表示的是每個級別縮進的空格數。比如,要在每個級別縮進4個空格:
~~~
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data, null, 4));
// 結果
{
"name": "tg",
"age": 1,
"books": [
"Javascript",
2
],
"location": {
"name": "gz"
}
}
~~~
當傳入有效的控制縮進的參數值時,結果字符串就會自動包含換行符。不過要注意:最大縮進空格數為10,所有大于10的值都會自動轉換為10.
如果縮進參數是一個字符串而非數值,則這個字符串將在JSON字符串中**被用作縮進字符**。
~~~
var data = {
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
},
test: function(){},
sex: undefined
};
console.log(JSON.stringify(data, null, 4));
// 結果
{
--"name": "tg",
--"age": 1,
--"books": [
----"Javascript",
----2
--],
--"location": {
----"name": "gz"
--}
}
~~~
注意:縮進字符串最長不能超過10個字符長,如果超過了10個,結果中只會顯示10個字符。
**3. toJSON()方法**
如果JSON.stringify的參數對象有自定義的toJSON方法,那么JSON.stringify會**使用這個方法的返回值作為參數**,而忽略原對象的其他屬性。
~~~
var data = {
name: 'tg',
age: 1,
toJSON:function(){
var data = {
name: this.name
};
return data;
}
};
console.log(JSON.stringify(data));
//{"name":"tg"}
~~~
在上面的代碼中,我們給data對象定義了一個toJSON()方法,該方法返回name的值。
可以為任何對象添加toJSON()方法,讓toJSON()方法返回任何序列化的值。
假設將一個對象傳入JSON.stringify(),序列化對象的順序如下:
1. 如果存在toJSON()方法而且能通過它取得有效的值,則調用該方法,否則,按默認順序序列化。
2. 如果提供了第二個參數,應用這個函數過濾器。傳入函數過濾器的值是第1步返回的值
3. 對第2步返回的每個值進行相應的序列化
4. 如果提供了第三個參數,執行相應的格式化
### 11.2.3 解析選項
JSON.parse方法用于**將JSON字符串轉化成原生的JavaScript對象。**
~~~
var jsonText = '{"name":"tg","age":1,"books":["Javascript",2],"location":{"name":"gz"}}';
console.log(JSON.parse(jsonText));
//返回對象
{
name: 'tg',
age: 1,
books: [ "Javascript", 2],
location:{
name: "gz",
}
};
~~~
如果傳入的字符串不是有效的JSON格式,則會報錯。
JSON.parse()還可以接收第二個參數,該參數是一個函數,將在每個鍵值對上調用。
~~~
var jsonText = '{"name":"tg","age":1,"books":["Javascript",2],"location":{"name":"gz"}};
var o = JSON.parse(jsonText,function(key, value){
if(key == "name"){
return "Hello";
}
return value;
});
console.log(o.name);
// Hello
~~~
在上面的例子中,在解析時,當遇到鍵名是“name”時,就將相應的值替換成"Hello",最終返回的name就是"Hello"。
如果函數返回undefined,則表示要從結果中刪除相應的鍵,如果返回其他值,則將其放入到結果中。
- 前言
- 第一章 JavaScript簡介
- 第三章 基本概念
- 3.1-3.3 語法、關鍵字和變量
- 3.4 數據類型
- 3.5-3.6 操作符、流控制語句(暫略)
- 3.7函數
- 第四章 變量的值、作用域與內存問題
- 第五章 引用類型
- 5.1 Object類型
- 5.2 Array類型
- 5.3 Date類型
- 5.4 基本包裝類型
- 5.5 單體內置對象
- 第六章 面向對象的程序設計
- 6.1 理解對象
- 6.2 創建對象
- 6.3 繼承
- 第七章 函數
- 7.1 函數概述
- 7.2 閉包
- 7.3 私有變量
- 第八章 BOM
- 8.1 window對象
- 8.2 location對象
- 8.3 navigator、screen與history對象
- 第九章 DOM
- 9.1 節點層次
- 9.2 DOM操作技術
- 9.3 DOM擴展
- 9.4 DOM2和DOM3
- 第十章 事件
- 10.1 事件流
- 10.2 事件處理程序
- 10.3 事件對象
- 10.4 事件類型
- 第十一章 JSON
- 11.1-11.2 語法與序列化選項
- 第十二章 正則表達式
- 12.1 創建正則表達式
- 12.2-12.3 模式匹配與RegExp對象
- 第十三章 Ajax
- 13.1 XMLHttpRequest對象
- 你不知道的JavaScript
- 一、作用域與閉包
- 1.1 作用域
- 1.2 詞法作用域
- 1.3 函數作用域與塊作用域
- 1.4 提升
- 1.5 作用域閉包
- 二、this與對象原型
- 2.1 關于this
- 2.2 全面解析this
- 2.3 對象
- 2.4 混合對象“類”
- 2.5 原型
- 2.6 行為委托
- 三、類型與語法
- 3.1 類型
- 3.2 值
- 3.3 原生函數