王磊的个人技术记录 王磊的个人技术记录

记录精彩的程序人生

目录
JSON.parse JSON.stringify
/  

JSON.parse JSON.stringify

以下内容转载自 https://www.cnblogs.com/liuzhongrong/p/12365265.html

本人仅做个人学习记录使用,如有侵权请留言删除。

1. 定义

stringify 函数的定义: JSON.stringify(value [, replacer [, space]])

参数:

  • value : 将要转为 JSON 字符串的 JavaScript 对象。
  • replacer :该参数可以是多种类型,如果是一个函数,则它可以改变一个 JavaScript 对象在字符串化过程中的行为, 如果是一个包含 String 和 Number 对象的数组,则它将作为一个白名单。只有那些键存在域该白名单中的键值对才会被包含进最终生成的 JSON 字符串中。如果该参数值为 null 或者被省略,则所有的键值对都会被包含进最终生成的 JSON 字符串中。
  • space :该参数可以是一个 String 或 Number 对象,作用是为了在输出的 JSON 字符串中插入空白符来增强可读性。 如果是 Number 对象, 则表示用多少个空格来作为空白符; 最大可为 10,大于 10 的数值也取 10.最小可为 1,小于 1 的数值无效,则不会显示空白符。 如果是个 String 对象, 则该字符串本身会作为空白符,字符串最长可为 10 个字符。超过的话会截取前十个字符。 如果该参数被省略 (或者为 null), 则不会显示空白符

1.1 替换函数可以用来过滤值

  1. 返回 undefined 表示忽略该属性
  2. 返回字符串,布尔值或则数字将会被 stringify
  3. 返回对象将会触发递归调用知道遇到基本类型的属性
  4. 返回无法 stringify 的值将会被忽略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let user = {
age: 18,
name: 'tom',
email: 'tom@caonima.com'
};

function (key, value) {
if (key === 'email') {
return undefined;
}
return value;
}

let str = JSON.stringify(user, replacer);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 过滤提取数据 
let data = [
{name: "tom", sex:1, age: 18},
{name: "jerry", sex:0, age: 17},
{name: "mike", test: {age: 15}} // 数组中的嵌套属性会被过滤
];

let str = JSON.stringify(data, ["name","age"]);
console.log(str);
//[{"name":"tom","sex":1},{"name":"jerry","sex":0},{"name":"mike"}]

// 处理数据
let str2 = JSON.stringify(data, function(key, val){
if(key === 'sex'){
return ['男', '女'][val]
}
return val
})
console.log(str2);
// [{"name":"tom","sex":"女","age":18},{"name":"jerry","sex":"男","age":17}]

1.2 使用 JSON.stringify() 做对象序列化

  1. undefined 值、函数或者 XML 值会被忽略
  2. 如果你的数组当中含有 undefined 值,函数或 XML 值,该数组中的这些值将会被当成 null
  3. 如果属性为 null 则可以正常序列化这个属性(因为 null 可表示已经赋值,而 undefined 表示未定义、未赋值,所以执行 JSON.stringify 不会处理。)
  4. 有些属性无法被 stringify (SON 是一个通用的文本格式,和语言无关。设想如果将函数定义也 stringify 的话,如何判断是哪种语言,并且通过合适的方式将其呈现出来将会变得特别复杂。特别是和语言相关的一些特性,比如 JavaScript 中的 Symbol。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let data = {
name: 'tom',
age: undefined,
sex: null,
fn: function() {
return true
}
}
JSON.stringify(data)
// {"name":"tom","sex":null}
< 大专栏  你不知道的JSON.stringify知识点span class="line">
// 在数组中,不可被 stringify 的元素用 null 填充
let arr = [Symbol(), undefined, function() {}, "tom"];
JSON.stringify(arr);
// "[null,null,null,'tom']"

1.3 使用 JSON.parse(JSON.stringify(obj))实现深拷贝

JSON.parse(JSON.stringify(obj)) 我们一般用来深拷贝,其过程说白了 就是利用 JSON.stringify 将 js 对象序列化(JSON 字符串),再使用 JSON.parse 来反序列化(还原)js 对象;序列化的作用是存储(对象本身存储的只是一个地址映射,如果断电,对象将不复存在,因此需将对象的内容转换成字符串的形式再保存在磁盘上 )和传输(例如 如果请求的 Content-Typeapplication/x-www-form-urlencoded ,则前端这边需要使用 qs.stringify(data) 来序列化参数再传给后端,否则后端接受不到; ps: Content-Typeapplication/json;charset=UTF-8 或者 multipart/form-data 则可以不需要 );我们在使用 JSON.parse(JSON.stringify(xxx)) 时应该注意一下几点:

  • 如果 obj 里面有时间对象,则 JSON.stringify 后再 JSON.parse 的结果,时间将只是字符串的形式。而不是时间对象;
  • 如果 obj 里有 RegExp、Error 对象,则序列化的结果将只得到空对象;
  • 如果 obj 里有函数,undefined,则序列化的结果会把函数或 undefined 丢失;
  • 如果 obj 里有 NaN、Infinity 和-Infinity,则序列化的结果会变成 null
  • JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果 obj 中的对象是有构造函数生成的, 则使用 JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的 constructor;
  • 如果对象中存在循环引用的情况也无法正确实现深拷贝;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//如果拷贝的对象不涉及上面讲的情况,可以使用JSON.parse(JSON.stringify(obj))实现深拷贝,但是涉及到上面的情况,可以考虑使用如下方法实现深拷贝:
function deepClone(data) {
const type = this.judgeType(data);
let obj;
if (type === 'array') {
obj = [];
} else if (type === 'object') {
obj = {};
} else { // 没有下一层次
return data;
}
if (type === 'array') { // eslint-disable-next-line
for (let i = 0, len = data.length; i < len; i++) {
obj.push(this.deepClone(data[i]));
}
} else if (type === 'object') {
// 对原型上的方法也拷贝了....
// eslint-disable-next-line
for (const key in data) {
obj[key] = this.deepClone(data[key]);
}
}
return obj;
},


function judgeType(obj) {
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object',
};
if (obj instanceof Element) {
return 'element';
}
// tostring会返回对应不同的标签的构造函数
return map[Object.prototype.toString.call(obj)];
},

注意

  • 不是所有的合法的 JSON 都是有效的 JavaScript
  • JSON 只是一个文本格式
  • JSON 中的数字是十进制

标题:JSON.parse JSON.stringify
作者:wanglei03
地址:https://wangleijava.com/articles/2020/03/09/1583733946322.html