当前位置:网站首页>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);

边栏推荐
- Description of the functional scenario of "collective storage and general governance" in the data center
- 融云「音视频架构实践」技术专场【内含完整PPT】
- Looking at the ecological potential of Hongmeng OS from the evolution of MatePad Pro
- 通用型安全监测数据管理系统
- 使用Stream多年,collect还有这些“骚操作”?
- C专家编程 第3章 分析C语言的声明 3.7 typedef struct foo{... foo;}的含义
- C专家编程 第2章 这不是Bug,而是语言特性 2.1 这关语言特性何事,在Fortran里这就是Bug呀
- PTA递归练习
- 双指针/滑动窗口问题
- 组件通信--下拉菜单案例
猜你喜欢

The strongest distributed lock tool: Redisson

【Metaverse系列一】元宇宙的奥秘
[redis] cache penetration and cache avalanche and cache breakdown solutions

为何微博又双叒叕崩溃了?

phoenix创建映射表和创建索引、删除索引

面试突击71:GET 和 POST 有什么区别?

工程仪器设备在线监测管理系统常见问题和注意事项

虹科分享 | 如何测试与验证复杂的FPGA设计(3)——硬件测试

SQL中对 datetime 类型操作

“LaMDA 存在种族歧视,谷歌的 AI 伦理不过是‘遮羞布’!”
随机推荐
请问下这个hologres维表是被缓存了么?怎么直接Finished了
leetcode-每日一题899. 有序队列(思维题)
生产环境如何删除表呢?只能在SQL脚本里执行 drop table 吗
sphinx error connection to 127.0.0.1:9312 failed (errno=0, msg=)
双指针/滑动窗口问题
怎么在opengauss中进行测试自己添加的新函数的性能(循环n次的运行时间)?
【Metaverse系列一】元宇宙的奥秘
deepstresam的插件配置说明,通过配置osd,设置字体的背景为透明
通俗理解apt-get 和pip的区别是什么
国内首发可视化智能调优平台,小龙带你玩转KeenTune UI
Understand the recommendation system in one article: Outline 02: The link of the recommendation system, from recalling rough sorting, to fine sorting, to rearranging, and finally showing the recommend
兄弟组件通信context
Which thread pool does Async use?
掌握Redis的Sentinel哨兵原理,可助你拿到25k的offer
【无标题】
广告电商系统开发之会员系统板块
SwinIR实战:详细记录SwinIR的训练过程
JS 字符串转 GBK 编码超精简实现
LeetCode·899.有序队列·最小表示法
C专家编程 第2章 这不是Bug,而是语言特性 2.2 多做之过