当前位置: 首页 > 科技观察

你会使用JSON.stringify()吗?

时间:2023-03-17 20:37:38 科技观察

前言JSON是一种轻量级的数据格式,可以轻松表示复杂的数据结构。JSON对象有两个方法:stringify()和parse()。在简单的情况下,这两种方法可以分别将JavaScript序列化为JSON字符串并将JSON解析为原生JavaScript值。本文重点介绍JSON.stringify()的使用方法和注意事项。一、用法1、基本用法JSON.stringify()可以将一个JavaScript对象序列化为一个JSON字符串。letjson1={title:"Json.stringify",author:["乘风破浪"],year:2021};letjsonText=JSON.stringify(json1);默认情况下,JSON.stringify()会输出不包含空格或缩进的JSON字符串,因此jsonText的值是这样的:"{"title":"Json.stringify","author":["RidingtheWaves"],"year":2021}"inthesequence在实例化JavaScript对象时,结果中有意省略了所有函数和原型成员。此外,还会跳过任何值为undefined的属性。您最终得到的是一种表示,其中所有实例属性都是有效的JSON数据类型。JSON.stringify()方法一共可以接受3个参数,其中两个是可选参数(分别是第二个和第三个参数)。这两个可选参数可用于指定序列化JavaScript对象的其他方式。第二个参数是过滤器,可以是数组也可以是函数;第三个参数是缩进生成的JSON字符串的选项。单独或组合使用这些参数可以更好地控制JSON序列化。2、第二个参数——filter如果第二个参数是一个数组,JSON.stringify()返回的结果将只包含数组中列出的对象属性。比如下面这个例子:letjson1={title:"Json.stringify",author:["Json.stringify"],year:2021,like:'frontend',weixin:'frontJS'};letjsonText=JSON.stringify(json1,['微信']);在这个例子中,JSON.stringify()方法的第二个参数是一个包含字符串“weixin”的数组。它对应于要序列化的对象中的属性,所以在生成的JSON字符串中只会包含这个属性:"{"weixin":"frontJS"}"如果第二个参数是一个函数,则行为不同。提供的函数接收两个参数:属性名(key)和属性值(value)。你可以根据这个key来决定对相应的属性进行什么样的操作。键始终是字符串,但如果值不属于键/值对,则将为空字符串。conststudents=[{name:'james',score:100,},{name:'jo??rdon',score:60,},{name:'kobe',score:90,}];functionreplacer(key,value){if(key==='score'){if(value===100){return'S';}elseif(value>=90){return'A';}elseif(value>=70){return'B';}elseif(value>=50){return'C';}else{return'E';}}returnvalue;}console.log(JSON.stringify(students,replacer,4))上面的代码,我们通过replacer替换从带有等级刻度的百分位数刻度的等级。值得注意的是,如果stringify的第二个参数是一个函数,并且其返回值是undefined,那么对应的属性就不会被序列化。如果返回其他值,返回值会替换原来的值进行序列化改变。3、第三个参数——字符串缩进JSON.stringify()方法的第三个参数控制缩进和空格。当该参数为值时,表示每一级缩进的空格数。例如,要在每个级别缩进4个空格,您可以这样做:letjson1={title:"Json.stringify",author:["JsonintheWaves"],year:2021};letjsonText=JSON.stringify(json1,空,4);这样得到的jsonText格式如下:{"title":"Json.stringify","author":["扬帆起航"],"year":2021}JSON.stringify()正在处理数据同时考虑数据转换和易读性,但易读性往往被忽视。4.toJSON()方法--自定义JSON序列化有时,对象需要在JSON.stringify()之上自定义JSON序列化。此时,可以给要序列化的对象添加toJSON()方法,序列化会根据这个方法返回合适的JSON表示。下面这个对象添加了自定义序列化的toJSON()方法:letjson1={title:"Json.stringify",author:["乘风破浪"],year:2021,like:'frontend',weixin:'frontJS',toJSON:function(){returnthis.author}};console.log(JSON.stringify(json1));//[“乘风破浪”]注意不能用箭头函数来定义toJSON()方法。主要原因是箭头函数的词法作用域是全局作用域,在这种情况下是不合适的。二、使用场景1、判断数组是否包含对象,或者判断对象是否相等。//判断数组中是否包含一个对象name:'浪中扬帆'};console.log(JSON.stringify(data).indexOf(JSON.stringify(val))!==-1);//true我们也可以使用JSON.stringify()方法来判断两个对象是否相等。//判断对象是否相等letobj1={a:1,b:2}letobj2={a:1,b:2,}console.log(JSON.stringify(obj1)===JSON.stringify(obj2))//true但是,这种方法有比较大的局限性。如果对象调整了key的顺序,就会判断错误!//调整对象键的位置后letobj1={a:1,b:2}letobj2={b:2,a:1,}console.log(JSON.stringify(obj1)===JSON.stringify(obj2))//假2。在使用localStorage/sessionStorage的时候,localStorage/sessionStorage默认只能存储字符串,但是在实际开发中,我们往往需要存储对象类型,所以这时候就需要使用json.stringify()将对象转换成一个存储时返回字符串,并在获取本地缓存时使用json.parse()将对象转换回来。//保存数据函数setLocalStorage(key,val){window.localStorage.setItem(key,JSON.stringify(val));};//获取数据函数getLocalStorage(key){letval=JSON.parse(window.localStorage.getItem(key));returnval;};//测试setLocalStorage('Test',['前端工匠','浪中行']);console.log(getLocalStorage('Test'));localStorage3,实现objectdeepcopy在开发过程中,有时候我们很怕影响到原始数据。我们经常对数据的副本进行深拷贝以进行任意操作。使用JSON.stringify()和JSON.parse()来实现深拷贝是一个非常好的选择。letarr1=[1,3,{username:'kobe'}];letarr2=JSON.parse(JSON.stringify(arr1));arr2[2].username='duncan';console.log(arr1,arr2)image.png是用JSON.stringify把对象转成JSON字符串,再用JSON.parse把字符串解析成对象。一条一条走完,就会生成一个新的对象,新的对象会开一个新的栈,实现深拷贝。这种方法虽然可以实现数组或者对象的深拷贝,但是不能处理函数和正则表达式,因为这两者是基于JSON处理后的。该函数不再是函数(变为空)。letarr1=[1,3,function(){},{username:'kobe'}];letarr2=JSON.parse(JSON.stringify(arr1));arr2[3].username='duncan';console.log(arr1,arr2)三、使用注意事项JSON.stringify()虽然很强大,但是有些属性是不能字符串化的。因此,在开发中需要注意以下几种情况,避免出现意想不到的bug。1.转换后的值有NaN和InfinityletmyletmyObj={name:"boatinthewaves",age:Infinity,money:NaN,};console.log(JSON.stringify(myObj));//{"name":"boatinthewaves","age":null,"money":null}JSON.stringify([NaN,Infinity])//[null,null]2.有未定义的任意函数和有两类symbol值:数组,undefined,任意函数,symbol值在序列化时会转为null.JSON.stringify([undefined,function(){},Symbol("")]);//'[null,null,null]'序列化时将忽略非数组、未定义、任意函数和符号值JSON.stringify({x:undefined,y:function(){},z:Symbol("")});//'{}'3.循环引用如果一个对象的属性值通过某种间接的方式指向对象本身,那么它就是一个循环引用。例如:letbar={a:{c:foo}};letfoo={b:bar};JSON.stringify(foo)这种情况下序列化会报错://错误信息UncaughtReferenceError:fooisnotdefinedat:3:84。当存在不可枚举的属性值时,默认忽略不可枚举的属性:letpersonObj=Object.create(null,{name:{value:"boatinginthewaves",enumerable:false},year:{value:"2021",enumerable:true},})console.log(JSON.stringify(personObj))//{"year":"2021"}4.总结JSON.stringify()用于将JavaScript对象序列化为一个JSON字符串,此方法有一些选项可用于更改默认行为以实现过滤或修改流程。不过也需要注意的是有些属性是不能字符串化的,所以在开发的时候要避免这些坑!参考JavaScript高级编程(第4版)慎用JSON.stringify你用JS格式化JSON吗?json.stringify()你所不知道的JSON.stringify的妙用