对象转json字符串属性顺序改变的原因是什么
_JSON.stringify()还能这么玩
对于JSON,相信⼤家应该都蛮熟悉的.不管是前端还是后端的童鞋,应该每天都会和JSON打交道吧.JSON是 JavaScript Object Notation(JavaScript对象表⽰法)的缩写,是⼀种轻量级的⽂本数据交换格式,⽐xml更⼩,更快,更易于解析
在JavaScript中,JSON对象包含两个⽅法,parse()和stringify(),前者⽤于反序列化,后者⽤于序列化.所谓的序列化,通俗的理解就是将⼀个对象变成字符串,⽽反序列化就是相对应相反的过程.
今天我们主要来讲讲其中的stringify()⽅法.虽然我们平时也都在⽤这个⽅法,但是我们往往会忽略这个⽅法的更进⼀步的⽤法.假如我们能⽤好这个⽅法,在实际的开发过程中就可以达到事半功倍的效果.
相信⼤家在平时的开发过程中,经常会⽤到console.log来打印输出结果.⽐如我们在下⾯打印⼀个对象:
let obj = {
name:'zhangsan',
age:undefined
}
console.log(obj)  // // {name: "zhangsan", age: undefined}
复制代码
会过滤哪些属性?
可以很清晰的在控制台输出结果,达到我们想要的结果.但是假如我们对象中的有的属性值是没有意义的.⽐如下⾯的代码中,年纪是个未定义的属性,我们不想要在控制台输出它该怎么办.这时就可以使⽤JSON.stringify()⽅法来达到过滤的⽬的
let obj = {
name:'zhangsan',
age:undefined
}
console.log(JSON.stringify(obj))  // {"name":"zhangsan"}
复制代码
我们可以看到此时的输出结果就已经把属性值为undefined这个age属性给过滤掉了.⽽这正是JSON.stringify()的其中⼀个特性.除
了undefined以外,属性值为任意函数或者symbol类型的,也会被过滤掉.
let obj = {
name:'zhangsan',
age:undefined,
f:() => { console.log(1) },
symbol:Symbol('This is a symbol')
}
console.log(JSON.stringify(obj))  // {"name":"zhangsan"}
复制代码
我们再来给这个对象添加⼀个属性.这次我们添加的是⼀个数组,⽽这个数组⾥⾯就有⼀些上⾯我们提到过的这些类型,结果⼜是如何呢?
age:undefined,
f:() => { console.log(1) },
symbol:Symbol('This is a symbol'),
arr:[1, undefined, 2, this.f, 3, Symbol('This is a symbol in array')]
}
console.log(JSON.stringify(obj))  // {"name":"zhangsan","arr":[1,null,2,null,3,null]}
复制代码
可以看到,undefined,函数和symbol类型的都变成了null. 下⾯我们还要⽤这⼏个类型来测试,假如我们直接使⽤JSON.stringify()来操作它们会怎么样呢?
console.log(JSON.stringify(undefined))  // undefined
console.log(JSON.stringify(() => { console.log(1) }))  // undefined
console.log(JSON.stringify(Symbol('This is a symbol')))  // undefined
复制代码
可以看到输出结果全是undefined.我们再来看看其他的某些特殊的值:
console.log(JSON.stringify(null))  // null
console.log(JSON.stringify(NaN))  // null
console.log(JSON.stringify(Infinity))  // null
复制代码
可以看到null,NaN,Infinity之类的都变成了null.
下⾯我们来看看转换包装对象的结果
console.log(JSON.stringify(new String('str')))  // "str"
console.log(JSON.stringify(new Boolean(true)))  // true
console.log(JSON.stringify(new Number(1)))  // 1
复制代码
可以看出字符串,布尔类型和数字的包装对象会在序列化的时候变成原始值
toJSON()⽅法
假如我们转换对象中有toJSON这个⽅法,那么返回的结果就由它决定:
let obj = {
name:'zhangsan',
toJSON:function(){
return 'customize return value'
}
}
console.log(JSON.stringify(obj))  // "customize return value"
复制代码
如果显⽰的定义了toJSON⽅法却没有return任何内容,那么结果就是undefined
toJSON:function(){}
}
console.log(JSON.stringify(obj))  // undefined
复制代码
这⾥⼜可以牵扯出另外⼀个对象类型Date.假如我们序列化⼀个Date类型,结果⼜是什么呢?
console.log(JSON.stringify(new Date()))  // "2020-06-20T14:21:15.071Z"
复制代码
可以看到输出了这种我们熟悉的时间格式,这是因为Date类型的对象就有⾃⼰的toJSON的实现
假如⼀个对象的属性是不可枚举的,那么也会被过滤掉
let obj = ate({},{
name:{
value:'zhangsan',
enumerable:false
json值的类型有哪些
},
age:{
value:18,
enumerable:true
}
})
console.log(obj)  // {age: 18, name: "zhangsan"}
console.log(JSON.stringify(obj))  // {"age":18}
复制代码
第⼆个参数
到上⾯为⽌,我们举例了⼀些JSON.stringify()的⽤法.很多⼈以为到这⾥就结束了,其实不是的,下⾯我们还要介绍它的第2个参数.
假如有这么⼀个对象,它有姓名,性别,年纪等多种属性.但是我们不想关⼼它的其他信息,只想知道它的名字是啥.⽽它的其他属性值都不是像那些undefined等⼀样是⽆意义的值,我们该如何过滤呢?
let obj = {
name:'zhangsan',
gender:'female',
age:18,
hobby:'swim'
}
console.log(JSON.stringify(obj,['age']))  // {"age":18}
复制代码
这时,我们的第2个参数就派上⽤场了.我们传⼊了⼀个数组,⽽这个数组中的值就是我们想要保留的属性名,不在这个数组之列的,全部都不要返回. 除了传⼊数组类型以外,我们还可以传⼊⼀个函数.
gender:undefined,
age:18,
hobby:'swim'
}
console.log(JSON.stringify(obj, (key, value) => {
if(typeof value === 'string'){
return undefined
}
return value
}))  // {"age":18}
复制代码
在函数中,我们做了⼀些逻辑判断,当属性值是字符串的时候,就给它过滤掉.使⽤这第⼆个参数,我们也可以改变属性值为undefined,symbol之类的原本不会返回的属性.
let obj = {
name:'zhangsan',
gender:undefined,
age:18,
hobby:'swim'
}
console.log(JSON.stringify(obj, (key, value) => {
if(typeof value === 'string'){
return undefined
}
if(typeof value === 'undefined'){
return 'not any more undefined'
}
return value
}))  // {"gender":"not any more undefined","age":18}
复制代码
再来结合toString()这个⽅法,我们来输出函数的具体内容:
let obj = {
name:'zhangsan',
f:function(){
console.log('I\'m a function')
}
}
console.log(JSON.stringify(obj, (key, value) => {
if(typeof value === 'function'){
return String.call(value)
}
return value
}))
// {"name":"zhangsan","f":"function(){\n    console.log('I\\'m a function')\n  }"}
复制代码
第三个参数
讲完了第2个参数,我们再来讲讲第3个参数.是的,你没有看错,它还有第三个参数.这个参数的主要作⽤是⽤来美化输出的json字符串.在没有第三个参数的时候,我们输出的字符串是挤在⼀堆的,不利于观看.有了它,我们就可以格式化我们的输出结果:
age:18,
gender:'female'
}
console.log(JSON.stringify(obj,null,2))
/*{
"name": "zhangsan",
"age": 18,
"gender": "female"
}*/
复制代码
第三个参数传⼊的类型是数字n的话,就表⽰每⼀级⽐它的上⼀级多缩进n个空格,n最⼤为10 第三个参数传⼊的类型是字符串的话,则会在每⼀级前⾯加上这个字符串,字符串的最⼤长度也是10
let obj = {
name:'zhangsan',
age:18,
gender:'female'
}
console.log(JSON.stringify(obj,null,'?'))
/*{
"name": "zhangsan",
"age": 18,
"gender": "female"
}*/
复制代码
总结: ⾄此,关于JSON.stringify()的⽤法,我们基本讲的差不多了.⼤部分的知识点我们就⽤下⾯的图来表⽰了.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。