当前位置:网站首页>JSON.stringify()的深入学习和理解
JSON.stringify()的深入学习和理解
2022-08-03 17:01:00 【欧菲斯集团】
一、JSON
JSON是一种轻量级数据格式,可以方便地表示复杂数据结构。JSON对象有两个方法:stringify()和parse()。在简单的情况下,这两个方法分别可以将JavaScript序列化为JSON字符串,以及将JSON解析为原生JavaScript值
二、JSON.stringify()
JSON.stringify(value[, replacer [, space]])
基本用法:JSON.stringify()
方法将一个 JavaScript 对象或值转换为 JSON 字符串
- 转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。
- 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
- 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
undefined
、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成null
(出现在数组中时)。函数、undefined 被单独转换时,会返回 undefined,如JSON.stringify(function(){})
orJSON.stringify(undefined)
.- 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
- 所有以 symbol 为属性键的属性都会被完全忽略掉,即便
replacer
参数中强制指定包含了它们。 - Date 日期调用了 toJSON() 将其转换为了 string 字符串(同 Date.toISOString()),因此会被当做字符串处理。
- NaN 和 Infinity 格式的数值及 null 都会被当做 null。
- 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。
console.log(JSON.stringify({
title: "Json.stringify", author: "欧菲斯", year: 2022}));
//output: {"title":"Json.stringify","author":"欧菲斯","year":2022}
默认情况下,JSON.stringify()会输出不包含空格或缩进的JSON字符串,在序列化JavaScript对象时,所有函数和原型成员都会有意地在结果中省略。此外,值为undefined的任何属性也会被跳过。最终得到的就是所有实例属性均为有效JSON数据类型的表示。
三、参数-replacer
replacer 参数可以是一个函数或者一个数组。作为函数,它有两个参数,键(key)和值(value),它们都会被序列化。在开始时,replacer
函数会被传入一个空字符串作为 key
值,代表着要被 stringify
的这个对象。随后每个对象或数组上的属性会被依次传入。
函数应当返回 JSON 字符串中的 value, 如下所示:
- 如果返回一个
Number
, 转换成相应的字符串作为属性值被添加入 JSON 字符串。 - 如果返回一个
String
, 该字符串作为属性值被添加入 JSON 字符串。 - 如果返回一个
Boolean
, “true” 或者 “false” 作为属性值被添加入 JSON 字符串。 - 如果返回任何其他对象,该对象递归地序列化成 JSON 字符串,对每个属性调用 replacer 方法。除非该对象是一个函数,这种情况将不会被序列化成 JSON 字符串。
- 如果返回 undefined,该属性值不会在 JSON 字符串中输出。
注意: 不能用 replacer 方法,从数组中移除值(values),如若返回 undefined 或者一个函数,将会被 null 取代。
- 参数为函数时
function replacer(key, value) {
if (typeof value === "string") {
return undefined;
}
return value;
}
let foo = {
title: "Json.stringify", author: "欧菲斯", year: 2022};
let jsonString = JSON.stringify(foo, replacer);
在这个例子中,repalcer函数将序列化 JavaScript 对象中value值不时string类型的属性返回undefined,故序列化后的JSON字符串只有year属性
- 参数为数组时
let foo = {
title: "Json.stringify", author: "欧菲斯", year: 2022};
let jsonString = JSON.stringify(foo, ['title','year']);
在这个例子中,repalcer是一个包含title、year字符串的数组,它对应着要序列化的对象中的属性,因此结果JSON字符串中只会包含这两个属性。
四、参数-space
space
参数用来控制结果字符串里面的间距。如果是一个数字,则在字符串化时每一级别会比上一级别缩进多这个数字值的空格(最多 10 个空格);如果是一个字符串,则每一级别会比上一级别多缩进该字符串(或该字符串的前 10 个字符)。
let foo = {
title: "Json.stringify", author: "欧菲斯", year: 2022, date: "7/31" ,time: "14:29"};
JSON.stringify(foo)
JSON.stringify(foo, null, '\t')
JSON.stringify()在处理数据的时候同时考虑了数据转换和方便阅读,只不过,方便阅读这一点,常常被人忽略。
五、toJSON()方法–自定义JSON序列化
如果一个被序列化的对象拥有 toJSON
方法,那么该 toJSON
方法就会覆盖该对象默认的序列化行为:不是该对象被序列化,而是调用 toJSON
方法后的返回值会被序列化。
let foo = {
year: '2021',
toJSON: function () {
return '2022';
}
};
JSON.stringify(foo); //'"2022"'
JSON.stringify({
year: foo}); //'{"year":"2022"}'
六、使用场景
1、判断数组是否包含某对象,或者判断对象是否相等。
let data = [ {
name:'json'}, {
name:'json'}, {
name:'json'}, ], val = {
name:'json'};
console.log(JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1); //true
我们还可以使用JSON.stringify()方法,来判断两个对象是否相等。
判断对象是否相等
let obj1 = {
a: 1, b: 2 };
let obj2 = {
a: 1, b: 2 };
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)) // true
不过这种方式存在着较大的局限性,对象如果调整了键的顺序,就会判断出错!
调整对象键的位置后
let obj1 = {
a: 1, b: 2 };
let obj2 = {
b: 2, a: 1 };
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)) // false
2、使用 JSON.stringify 结合 localStorage
localStorage/sessionStorage默认只能存储字符串,而实际开发中,我们往往需要存储对象类型,那么此时我们需要在存储时利用json.stringify()将对象转为字符串,在取本地缓存时,使用json.parse()转回对象即可。
let foo = {
title: "Json.stringify", author: "欧菲斯", year: 2022, date: "7/31" ,time: "14:29"};
window.localStorage.setItem('foo', JSON.stringify(foo));
3、实现对象深拷贝
开发中,有时候怕影响原数据,我们常深拷贝出一份数据做任意操作,使用JSON.stringify()与JSON.parse()来实现深拷贝是很不错的选择。
let arr1 = [1, 3, {
username: 'yanss'}];
let arr2 = JSON.parse(JSON.stringify(arr1));
arr2[2].username = 'binss';
console.log(arr1, arr2)
这是利用JSON.stringify将对象转成JSON字符串,再用JSON.parse把字符串解析成对象,一去一来,新的对象产生了,新对象会开辟新的栈,实现深拷贝。
这种方法虽然可以实现数组或对象深拷贝,但不能处理函数和正则,因为这两者基于JSON.stringify和JSON.parse处理后,得到的正则就不再是正则(变为空对象),得到的函数就不再是函数(变为null)了。
let arr1 = [1, 3, function () {
}, {
username: 'yanss'}];
let arr2 = JSON.parse(JSON.stringify(arr1));
arr2[3].username = 'binss';
console.log(arr1, arr2);
边栏推荐
猜你喜欢
随机推荐
Components of communication - the drop-down menu
After using Stream for many years, does collect still have these "saucy operations"?
【数据库数据恢复】SqlServer数据库无法读取的数据恢复案例
security加密解密
C语言03、数组
并发高的情况下,试试用ThreadLocalRandom来生成随机数
Description of the functional scenario of "collective storage and general governance" in the data center
SwinIR实战:如何使用SwinIR和预训练模型实现图片的超分
中小微企业如何简单便捷、低成本实现数字化?360视觉云有妙招
LeetCode·899.有序队列·最小表示法
protobuf 反射使用总结
C专家编程 第3章 分析C语言的声明 3.4 通过图标分析C语言的声明
[Unity Getting Started Plan] Basic Concepts (7) - Input Manager & Input Class
学会 Arthas,让你 3 年经验掌握 5 年功力!
Web3的开源为何会如此受到人们喜爱?
国内首发可视化智能调优平台,小龙带你玩转KeenTune UI
EasyExcel implements dynamic column parsing and table storage
LeetCode·1163.按字典序排在最后的子串·最小表示法
303. Range Sum Query - Immutable
工程仪器设备在线监测管理系统常见问题和注意事项