1. 基礎知識
1. 什么是JSON格式?
JSON格式是現在網站數據交互的標准數據格式,寫入標准。
- 取代原來的XML;符合JS原生語法,可以被直接解析,不需要額外的解析文件。
- 書寫簡單,一目了然
2. 合格的JSON數據
1.對象{...}
1)屬性名必須是雙引號的字符串;不能是Symbol類型;會被忽略
2)屬性值不能是Date類型、函數、正則表達式、undefined、NaN、Infinity、-Infinity
JSON.stringify(value)的作用是將值轉化為JSON的字符串形式。
JSON.stringify({a: new Date()}); // "{"a":"2019-10-12T15:16:13.833Z"}" // new Date()由於toJSON()方法的存在,由對象變成了字符串類型,Date.parse()無法復原JSON JSON.stringify({[symbol()]: 5}); // "{}" Symbol的屬性被忽略 JSON.stringify({a: function(){}}); // "{}" function的屬性值被忽略 JSON.stringify({a: undefined}); // "{}" undefined的屬性值被忽略 JSON.stringify({a: /a/}); // "{"a": {}}" 正則表達式被解析成{} JSON.stringify({a: NaN}); // "{"a": null}" NaN被解析成null JSON.stringify({a: Infinity}); // "{"a": null}" Infinity被解析成null JSON.stringify({a: -Infinity}); // "{"a": null}" -Infinity被解析成null
3)屬性值如果含有字符串,必須全部是雙引號
var obj={ //這是個對象,不是JSON a: ['k','m'], b: 'n', c: {d: 'e'} } JSON.stringify(obj); /* 標准的JSON格式如下: "{ "a": ["k", "m"], "b": "n", "c": {"d": "e"} }" */
let obj ={a: 1} let obj2 = {b: 2}; obj.c = obj2; obj2.d = obj; JSON.stringify(obj2); //Uncaught TypeError: Converting circular structure to JSON
5) 合格的JSON格式數據最后一個元素后面不能有,
JSON.stringify({a:1,}); // "{"a":1}" 轉為JSON格式,逗號消失,說明JSON不能有逗號
2. 數組[]
數組的元素不能是Date,Symbol,RegExp,function,NaN,undefined,Infinity,-Infinity。
除了正則表達式會被解析成{ }, 其余6個都會被解析成null
最后一個元素后面不能有逗號(,)
JSON.stringify([Symbol(), undefined, NaN, Infinity,-Infinity,function(){}, /a/]); // "[null,null,null,null,null,null,{}]"
3. 原始數據類型
字符串、數字(十進制)、布爾值、null
JSON.stringify('true');// ""true"" 將字符串單引號變為雙引號,再字符串化 JSON.stringify('true') === "\"true\"" ;// true JSON.stringify(0x99); // "153" 不能是十進制以外的數字,會被自動轉為十進制,通過JSON.parse()無法還原 JSON.stringify(99); //"99" JSON.stringify(true); // "true" JSON.stringify(null); //"null"
❎不能是:Symbol、undefined、NaN、Infinity、-Infinity
前兩個會被忽略,和空函數一樣,默認返回undefined
后面的會被解析成null
JSON.stringify(Symbol()); // undefined JSON.stringify(undefined);// undefined JSON.stringify(NaN); // "null" JSON.stringify(Infinity); // "null" JSON.stringify(-Infinity); // "null"
2. JSON.stringify(value[, replacer, space])
該方法將任意類型的值,轉為JSON對象的字符串格式。
1)如果對象有自定義的toJSON方法,value將是toJSON的返回值
Date對象原生含有toJSON()方法。將對象轉為字符串,所以Date對象不能作為JSON格式的值。
// 自定義toJSON()方法 var obj={ a: 1, toJSON(){ return {c:1} } }; JSON.stringify(obj); //"{"c":1}"
2)當value是對象時,會過濾掉不可遍歷屬性
var obj = {}; Object.defineProperties(obj, { "foo": { value: 5, enumerable: false }, "bar": { value: 6, enumerable: true } }); obj; // {foo: 5, bar; 6} JSON.stringify(obj); // "{"bar": 6}"
3) 第二個參數可以是數組,只有當value是對象時,表示可以遍歷的屬性;
var obj = { foo: {bar: 5}, bar: {foo: 6}, tar: 7 }; JSON.stringify(obj, ['foo']); // "{"foo": {}}" 因為第二個參數規定了只序列化foo屬性,嵌套的屬性也適用該規則
第二個參數還可以是函數function(key,value){},用於處理數據;而且可以遞歸處理所有的屬性。
該函數默認形式是:
funtion(key,value){ return value; }
不論第一個參數是什么類型的值,函數第一次處理的key都沒有對應,value是本身;
如果返回的value值不是原始數據類型,則遞歸調用函數,函數對應的處理對象都是上次返回的結果。
a. 當value是對象時,key,value對應對象的鍵值對
JSON.stringify({a:1,b:2}, function(key,value) { console.log("key=",key, "value=",value); return value }) // "{"a":1,"b":2}" // key= value= {a: 1, b: 2} // key= a value= 1 // key= b value= 2 JSON.stringify({a:1,b:2}, function(key,value) { if(typeof value === 'number') { value += 10; } return value; }); // "{"a": 11, "b":12}"
b. 當value是數組時,key對應數組下標, value對應值
JSON.stringify([1,2], function(key,value){ console.log("key=",key, "value=",value); return value; }) //"[1,2]" // key= value= [1, 2] // key= 0 value= 1 // key= 1 value= 2
c. 當value是原始類型的值時, 不需要遞歸調用
JSON.stringify(5, function(key,value){ return value+5}) //"10" JSON.stringify('5', function(key,value){ return value+5}) // "55"
4)第三個參數主要用來增加可讀性,調整返回格式;
如果參數是一個數字(<10),表示在返回的屬性面前的空格數量;
JSON.stringify({a: {b:1}}, function(key,value) { return value }, 4); /* "{ "a": { "b": 1 } } */
如果參數是一個字符串(length<10), 表示在屬性前面添加該字符串
JSON.stringify({a: {b:1}}, function(key,value) { return value }, '|--'); /* "{ |--"a": { |--|--"b": 1 |--} }" */
3.JSON.parse(value[, function(key,value){}])
JSON.parse(value)將JSON對象的字符串形式,轉為JSON對象;
value必須是合格JSON數據的字符串,否則會拋出異常!
所以JSON.parse方法在不能確認參數是否正常的情況下,應該try...catch...
try{ JSON.parse("'test'"); // 最外層的引號是字符串格式,里面是JSON數據'test',單引號拋出異常 } catch { console.log("參數格式錯誤"); } // 其實如果是('"test"')不會拋出異常,字符串包含的是JSON數據"test"
第二個參數的用法同JSON.stringify()的第二個參數是函數的用法。