标签:美化 一个 枚举 遇到 处理 缩进 back 用法 研究
以前用到JSON的场景也不少,但是没有仔细的研究过,这几天趁着一个需求用到了,就整理了一下相关用法。
一、 JSON.stringify()
1. 语法 JSON.stringify(value[, replacer [, space]])
2. 先说一下后面两个可选参数
space:是指定缩进用的空白字符串,用于美化输出,可以是数字或字符串。
1 const data = { 2 a: ‘bang‘, 3 b: null, 4 c: { 5 x: ‘xxx‘, 6 y: ‘yyy‘, 7 z: 90 8 }, 9 d: 9527 10 } 11 JSON.stringify(data, null, 4) 12 // { 13 // "a": "bang", 14 // "b": null, 15 // "c": { 16 // "x": "xxx", 17 // "y": "yyy", 18 // "z": 90 19 // }, 20 // "d": 9527 21 // } 22 JSON.stringify(data, null, ‘-‘) 23 // { 24 // -"a": "bang", 25 // -"b": null, 26 // -"c": { 27 // --"x": "xxx", 28 // --"y": "yyy", 29 // --"z": 90 30 // -}, 31 // -"d": 9527 32 // }
replacer:转化规则,可以是一个函数或数组。
1 // 1. 数组 2 const data = { 3 a: ‘haha‘, 4 b: 123, 5 c: { 6 d: 8080, 7 e: null 8 } 9 }; 10 JSON.stringify(data, [‘b‘, ‘d‘]) 11 // {"b":123} 12 JSON.stringify(data, [‘a‘, ‘c‘]) 13 // {"a":"haha","c":{}} 14 JSON.stringify(data, [‘a‘, ‘c‘, ‘e‘]) 15 // {"a":"haha","c":{"e":null}}
1 // 2. 函数 2 const data = { 3 a: ‘haha‘, 4 b: 123, 5 c: { 6 b: ‘123‘, 7 d: 8080, 8 e: null 9 } 10 }; 11 function rep (key, value) { 12 if (key === ‘b‘ && typeof value === ‘number‘) return ++value; 13 return value; 14 } 15 JSON.stringify(data, rep) 16 // {"a":"haha","b":124,"c":{"b":"123","d":8080,"e":null}}
3. value
将要序列化成 一个 JSON 字符串的值。这里面有一些类型是不能够转化的,undefined/function/symbol
1). undefined
JSON.stringify遇到undefined时,是无法被返回的,但是null是可以的,所以我在这里的处理是把undefined 转化成null
这么做的理由是因为 undefined == null //true , 这样处理后的数据是不影响做模糊判断的。
2). function
同样是无法被返回的一种类型,我的处理是转成string类型存储,这么做产生的一个问题是 JSON.parse时需要再转成function
1 let data = { 2 name: undefined, 3 age: 18, 4 type: null, 5 fn: ()=>{ 6 return 999; 7 } 8 }; 9 let rep = (key, value) => { 10 if (value === undefined) { 11 return null; 12 } 13 if (typeof value === ‘function‘) { 14 return Function.prototype.toString.call(value); 15 } 16 return value; 17 } 18 JSON.stringify(data, rep) 19 //{"name":null,"age":18,"type":null,"fn":"()=>{\n return 999;\n }"}
3). symbol
es6新增的一种数据类型,具体留到另一篇文章里说。这里还是说JSON的问题。
1 // 当value是Symbol 时,能被第二个参数指定,若不指定则无法返回 2 // 当key是Symbol 时,会被忽略,第二个参数无法指定 3 let data={name: ‘aaa‘, symbol: Symbol()}; 4 data[Symbol()] = ‘bbb‘; 5 JSON.stringify(data,(key,value)=>{ 6 console.log(key,value); 7 // name aaa 8 // symbol Symbol() 9 if (typeof value === ‘symbol‘) return ‘symbol‘; //只有在这里指定才能返回结果 10 return value; 11 }); 12 //{"name":"aaa","symbol":"symbol"}
如果value 为Symbol,可以通过第二个参数来转换;但是key为Symbol的话,遍历的时候是无法遍历到的,就无法返回,类似于不可枚举类型:
1 let data = Object.create(null, { 2 name: { 3 value: ‘aaa‘, 4 enumerable: true 5 }, 6 age: { 7 value: 18, 8 enumerable: false 9 } 10 }); 11 let a = JSON.stringify(data, (key, value) => { 12 console.log(key, value); 13 //name aaa 14 return value; 15 }) 16 console.log(a); 17 //{"name":"aaa"}
二、JSON.parse()
1. 语法: JSON.parse(text[, reviver])
2. 参数:reviver 转换器, 如果传入该参数(函数),可以用来修改解析生成的原始值,调用时机在parse函数返回之前。
1 let data = { 2 name: undefined, 3 age: 18, 4 type: null, 5 fn: () => { 6 return 999; 7 } 8 }; 9 let rep = (key, value) => { 10 if (value === undefined) { 11 return null; 12 } 13 if (typeof value === ‘function‘) { 14 return Function.prototype.toString.call(value); 15 } 16 return value; 17 } 18 let jsonS = JSON.stringify(data, rep); 19 //{"name":null,"age":18,"type":null,"fn":"()=>{\n return 999;\n }"} 20 let jsonR = JSON.parse(jsonS, (key, value)=>{ 21 if (key) { 22 // return eval(‘(‘+value+‘)‘); 23 return new Function(‘return ‘+value)() 24 } 25 return value; 26 }); 27 console.log(jsonR, jsonR.fn()); 28 // { name: null, age: 18, type: null, fn: [Function] } 29 // 999
对于reviver 函数的处理用了eval 和 new Function 两种方式,因为eval的安全性问题,并不推荐使用,优先使用后一种方式。
三、toJSON
如果有toJSON,执行 .stringify时会先执行这个方法,再执行第二个参数
toJSON 是一个覆盖函数,要慎重使用。
1 let data = { 2 name: ‘nan‘, 3 age: 18, 4 toJSON: function () { 5 console.log(‘to‘); 6 return this.name; 7 } 8 }; 9 JSON.stringify(data, (key,value)=>{ 10 console.log(‘rep‘); 11 return value; 12 }); 13 // to 14 // rep 15 // "nan"
总结:对象中尽量只存储基础数据类型,尽量避免以上几种对于数据化不友好的类型。
JSON.stringify & JSON.parse 简析
标签:美化 一个 枚举 遇到 处理 缩进 back 用法 研究
原文地址:https://www.cnblogs.com/isnan/p/11883109.html