当前位置:网站首页>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);
边栏推荐
- 设置海思芯片MMZ内存、OS内存详解
- 论文解读(JKnet)《Representation Learning on Graphs with Jumping Knowledge Networks》
- “LaMDA 存在种族歧视,谷歌的 AI 伦理不过是‘遮羞布’!”
- C专家编程 第2章 这不是Bug,而是语言特性 2.3 误做之过
- JS 字符串转 GBK 编码超精简实现
- 使用uniapp 封装一个request 请求
- 【数仓】数据质量监控
- Component communication - parent-child component communication
- 【指针初解】
- Huawei, Lenovo, BAIC, etc. were selected as the first batch of training bases for "Enterprise Digital Transformation and Security Capability Improvement" by the Ministry of Industry and Information Te
猜你喜欢
设置海思芯片MMZ内存、OS内存详解
FinClip | July 2022 Product Highlights
使用deepstream消息发送功能的时候,检测框没有检测标签,No text labels of bboxes displayed with osd for deepstream-test5
使用uniapp 封装一个request 请求
The strongest distributed lock tool: Redisson
大型企业数据治理的现状和解决方案有哪些参考?_光点科技
B站回应HR称核心用户是Loser;微博回应宕机原因;Go 1.19 正式发布|极客头条
2年开发经验去面试,吊打面试官,即将面试的程序员这些笔记建议复习
Interviews are no longer hanged!This is the correct way to open the seven schemes of Redis distributed locks
“68道 Redis+168道 MySQL”精品面试题(带解析),你背废了吗?
随机推荐
“LaMDA 存在种族歧视,谷歌的 AI 伦理不过是‘遮羞布’!”
为何微博又双叒叕崩溃了?
node connection mongoose database process
Huawei, Lenovo, BAIC, etc. were selected as the first batch of training bases for "Enterprise Digital Transformation and Security Capability Improvement" by the Ministry of Industry and Information Te
面试不再被吊打!这才是Redis分布式锁的七种方案的正确打开方式
C语言01、数据类型、变量常量、字符串、转义字符、注释
C专家编程 第3章 分析C语言的声明 3.8 理解所有分析过程的代码段
5. Longest Palindromic Substring
工程仪器设备在线监测管理系统常见问题和注意事项
为什么我用了Redis之后,系统的性能却没有提升
大佬们。使用flink-cdc-sqlserver 2.2.0 版本读取sqlserver2008R
C语言03、数组
TiKV & TiFlash accelerate complex business queries丨TiFlash application practice
J9数字虚拟论:元宇宙的潜力:一股推动社会进步的力量
security加密解密
【数仓】数据质量监控
The strongest distributed lock tool: Redisson
[Unity Getting Started Plan] Basic Concepts (7) - Input Manager & Input Class
沃尔沃:这是会“种草”的“安全感”!
工程仪器设备在线监测管理系统常见问题和注意事项