本文內容主要引用在微信公眾號上看到的一片文章,因為自己對Json了解不是很深入,所以就整理出這篇博文與大家分享!
一、 JSON是一種格式,基於文本,優於輕量,用於交換數據
1.一種數據格式
數據的傳遞是一樣的,但是你可以看到形式是可以各式各樣的,這就是各種不同格式化后的數據,JSON是其中一種表示方式。
2.基於文本的數據格式
JSON是基於文本的數據格式,相對於基於二進制的數據,所以JSON在傳遞的時候是傳遞符合JSON這種格式(至於JSON的格式是什么我們第二部分再說)的字符串,我們常會稱為“JSON字符串”。
3.輕量級的數據格式
在JSON之前,有一個數據格式叫 xml,現在還是廣泛在用,但是JSON更加輕量,如 xml需要用到很多標簽,像上面的例子中,你可以明顯看到 xml格式的數據中標簽本身占據了很多空間,而JSON比較輕量,即相同數據,以JSON的格式占據的帶寬更小,這在有大量數據請求和傳遞的情況下是有明顯優勢的。
4.被廣泛地用於數據交換
輕量已經是一個用於數據交換的優勢了,但更重要的JSON是易於閱讀、編寫和機器解析的,即這個JSON對人和機器都是友好的,而且又輕,獨立於語言(因為是基於文本的),所以JSON被廣泛用於數據交換。
以前端JS進行ajax的POST請求為例,后端PHP處理請求為例:
- 前端構造一個JS對象,用於包裝要傳遞的數據,然后將JS對象轉化為JSON字符串,再發送請求到后端;
- 后端PHP接收到這個JSON字符串,將JSON字符串轉化為PHP對象,然后處理請求。
可以看到,相同的數據在這里有3種不同的表現形式,分別是前端的JS對象、傳輸的JSON字符串、后端的PHP對象,JS對象和PHP對象明顯不是一個東西,但是由於大家用的都是JSON來傳遞數據,大家都能理解這種數據格式,都能把JSON這種數據格式很容易地轉化為自己能理解的數據結構,這就方便啦,在其他各種語言環境中交換數據都是如此。
二、 JSON和JS對象之間的“八卦”
1. 兩個本質不同的東西為什么那么密切
"JSON"全名"JavaScript Object Notation",所以它的格式(語法)是基於JS的,但它就是一種格式,而JS對象是一個實例,是存在於內存的一個東西。
此外,JSON是可以傳輸的,因為它是文本格式,但是JS對象是沒辦法傳輸的,在語法上,JSON也會更加嚴格,但是JS對象就很松了。那么兩個不同的東西為什么那么密切,因為JSON畢竟是從JS中演變出來的,語法相近。
2. JSON格式別JS對象語法表現上嚴格在哪
- 鍵名: JSON必須加雙引號,JS對象可允許不加、加單引號、加雙引號
- 屬性值: JSON只能是數值(10進制)、字符串(雙引號)、布爾值和null,也可以是數組或者符合JSON要求的對象,不能是函數、NaN, Infinity, -Infinity和undefined。
- 數值: JSON前導0不能用,小數點后必須有數字,JS無限制。
3. 一個有意思的地方,JSON不是JS的子集
var code = '"\u2028\u2029"';
JSON.parse(code); // works fine
eval(code); // fails
上述代碼這兩個字符 \u2028和 \u2029分別表示行分隔符和段落分隔符,JSON.parse可以正常解析,但是當做js解析時會報錯。
三、 JS中與JSON相關的幾個函數
1. 將JS數據結構轉化為JSON字符串 —— JSON.stringify
JSON.stringify(value[, replacer [, space]])
**1.1** 基本使用 —— 僅需一個參數
JSON.stringify({"name":"Good Man","age":18})返回一個字符串 "{"name":"GoodMan","age":18}"。
1.2 第二個參數可以是函數,也可以是一個數組
-
如果第二個參數是一個函數,那么序列化過程中的每個屬性都會被這個函數轉化和處理。
-
如果第二個參數是一個數組,那么只有包含在這個數組中的屬性才會被序列化到最終的JSON字符串中。
-
如果第二個參數是null,那作用上和空着沒啥區別,但是不想設置第二個參數,只是想設置第三個參數的時候,就可以設置第二個參數為null。
** 第二個參數為函數**
var friend={
"firstName": "Good",
"lastName": "Man",
"phone":"1234567",
"age":18
};
var friendAfter=JSON.stringify(friend,function(key,value){
if(key==="phone")
return "(000)"+value;
else if(typeof value === "number")
return value + 10;
else return value; //如果你把這個else分句刪除,那么結果會是undefined
});
console.log(friendAfter);//輸出:{"firstName":"Good","lastName":"Man","phone":"(000)1234567","age":28}
這第二個參數若是數組
var friend={
"firstName": "Good",
"lastName": "Man",
"phone":"1234567",
"age":18
};
//注意下面的數組有一個值並不是上面對象的任何一個屬性名
var friendAfter=JSON.stringify(friend,["firstName","address","phone"]);
console.log(friendAfter);//{"firstName":"Good","phone":"1234567"}
//指定的“address”由於沒有在原來的對象中找到而被忽略
1.3 第三個參數用於美化輸出,不建議使用
1.4 注意事項(重要)
-
鍵名不是雙引號的(包括沒有引號或者是單引號),會自動變成雙引號;字符串是單引號的,會自動變成雙引號
-
最后一個屬性后面有逗號的,會被自動去掉
-
非數組對象的屬性不能保證以特定的順序出現在序列化后的字符串中
這個好理解,也就是對非數組對象在最終字符串中不保證屬性順序和原來一致 -
布爾值、數字、字符串的包裝對象在序列化過程中會自動轉換成對應的原始值 ,也就是你的什么new String("bala")會變成"bala",new Number(2017)會變成2017
-
undefined、任意的函數以及 symbol 值(symbol詳見ES6對symbol的介紹)出現在非數組對象的屬性值中:在序列化過程中會被忽略出現在數組中時:被轉換成 null
-
NaN、Infinity和-Infinity,不論在數組還是非數組的對象中,都被轉化為null
-
所有以 symbol 為屬性鍵的屬性都會被完全忽略掉,即便replacer 參數中強制指定包含了它們
-
不可枚舉的屬性會被忽略
**2. 將JSON字符串解析為JS數據結構 —— JSON.parse**
JSON.parse(text[, reviver])
值得注意的是這里有一個可選的第二個參數,這個參數必須是一個函數,這個函數作用在屬性已經被解析但是還沒返回前,將屬性處理后再返回。
var friend={
"firstName": "Good",
"lastName": "Man",
"phone":{"home":"1234567","work":["7654321","999000"]}
};
//我們先將其序列化
var friendAfter=JSON.stringify(friend);
//'{"firstName":"Good","lastName":"Man","phone":{"home":"1234567","work":["7654321","999000"]}}'
//再將其解析出來,在第二個參數的函數中打印出key和value
JSON.parse(friendAfter,function(k,v){
console.log(k);
console.log(v);
console.log("----");
});
/*
firstName
Good
----
lastName
Man
----
home
1234567
----
0
7654321
----
1
999000
----
work
[]
----
phone
Object
----
Object
----
*/
仔細看一下這些輸出,可以發現這個遍歷是由內而外的,可能由內而外這個詞大家會誤解,最里層是內部數組里的兩個值啊,但是輸出是從第一個屬性開始的,怎么就是由內而外的呢?
這個由內而外指的是對於復合屬性來說的,通俗地講,遍歷的時候,從頭到尾進行遍歷,如果是簡單屬性值(數值、字符串、布爾值和null),那么直接遍歷完成,如果是遇到屬性值是對象或者數組形式的,那么暫停,先遍歷這個子JSON,而遍歷的原則也是一樣的,等這個復合屬性遍歷完成,那么再完成對這個屬性的遍歷返回。
本質上,這就是一個深度優先的遍歷。
注意:如果 reviver 返回 undefined,則當前屬性會從所屬對象中刪除,如果返回了其他值,則返回的值會成為當前屬性新的屬性值。
3. 影響 JSON.stringify 的神奇函數 —— object.toJSON
如果你在一個JS對象上實現了toJSON方法,那么調用JSON.stringify去序列化這個JS對象時,JSON.stringify會把這個對象的toJSON方法返回的值作為參數去進行序列化。
var info={
"msg":"I Love You",
"toJSON":function(){
var replaceMsg=new Object();
replaceMsg["msg"]="Go Die";
return replaceMsg;
}
};
JSON.stringify(info);
//返回的是:'"{"msg":"Go Die"}"'
### 引用文章: