37.JavaScript对象与JSON格式的转换,JSON.stringify、JSON.parse方法的使用方法和注意事项_js将对象转为json格式
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
JSON处理
JSON
JavaScript Object Notation
是JavaScript
表达值和对象的通用数据格式其本质就是符合一定规范的字符串。由于JSON
的优良特性非常容易和其他语言进行数据交换尤其在前后端交互方面。即使我们前端使用JavaScript
后端使用Java/PHP/Python
同样可以使用JSON
格式的数据轻松交换。
JSON.stringify
JavaScript
为我们提供了简单的方法可以实现对象和字符串之间的转化。
JSON.stringify
将对象转为JSON
字符串JSON.parse
将JSON
字符串转为对象
例如我们把一个对象Dog
使用 JSON.string
转为JSON
字符串
let Dog = {
name:'Peter',
age:187,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[
{
name:'little peter01',
age:2,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
},
{
name:'little peter02',
age:3,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
}
]
}
let dogJson = JSON.stringify(Dog)
console.log(typeof dogJson)
console.log(dogJson)
代码的执行效果
可见使用JSON.stringify(obj)
方法会返回该对象obj
的JSON
字符串数据这个转换的过程可以称作JSON编码JSON-encoded、序列化serialized亦或者编组化marshalled。当对象转为普通的字符串后我们就可以以普通数据的格式存储、传递这些数据。
如果我们把这些字符串写入数据库就相当于把JavaScript
对象存进了数据库。
注意
JSON
编码的对象统一使用双引号没有单引号和反引号- 对象的属性名也用双引号这是强制的
JSON
已经发展成为了独立的数据规范因此归属于JavaScript
语言本身的非数据属性会被JSON.stringify
跳过。
包括
- 对象方法
- Symbol类型
- undefined的属性
let user = {
sayHello(){//函数被忽略
console.log('hello world');
},
[Symbol('id')]:996996,//Symbol被忽略
val:undefined//undefined值被忽略
}
console.log(JSON.stringify(user))
代码执行效果
可以看到里面啥也没有。
stringify的限制
并非所有的对象都能转为JSON
格式如果对象之间存在循环引用就会导致转换失败。
let father = {}
let son = {}
father.son = son
son.father = father
JSON.stringify(father)
代码执行结果
这里出现错误的原因就是存在对象间的循环引用Father
引用了Son
而Son
又反过来引用了Father
。
排除和替换
如果我们只希望将对象的个别属性转为JSON
格式或者摆出循环应用中的属性应该怎么做呢
JSON.stringify
已经为我们提供了解决方法
let json = JSON.stringify(obj[,replacer,space])
参数解读
obj
要编码的对象replacer
要编码的属性数组或者映射函数function(k,v)
space
用于格式化的空格数量
举个例子
let father = {
name:'father',
age:28
}
let son = {
name:'son',
age:4
}
father.son = son;
son.father = father;
console.log(JSON.stringify(father,['name','age']))
代码的执行结果如下
如果我们在第二个参数传入一个数组那么JSON.stringify
就会只把数组中的名称转为JSON
格式这样计算对象存在循环引用同样能够成功的转格式。
如果我们希望序列化出循环应用外的所有对象属性只需要把对象的所有属性名写入数组即可这对对象的子对象同样生效。
举个例子
let father = {
name:'father',
age:28,
car:{
car_name : "BYD",
car_age:3,
}
}
console.log(JSON.stringify(father,['name','car','car_name']))
代码执行结果
但是还存在一个问题如果对象属性特别多可能数组就会非常长代码也会很冗长。
这种情况下就需要使用映射函数
映射函数
我们可以创建一个函数代替数组作为replacer
这个函数接收(key,value)
作为参数并决定如何序列化对应的属性。
例如在解决循环引用的时候我们排除引用属性
let father = {
name:'father',
age:28,
car:{
car_name : "BYD",
car_age:3,
}
}
let son = {
name:'son',
age:4
}
father.son = son;
son.father = father;
console.log(JSON.stringify(father,function replacer(key,value){
console.log(`${key}:${value}`)
return (key=='son')?undefined:value;
}))
代码执行结果如下
由于值为undefined
的属性会被JSON.stringify
忽略这样我们就可以轻松的排除所有不希望出现的属性了。
格式化使用的空格数量
JSON.stringify(value, replacer, spaces)
的第三个参数spaces
可以指定JSON
字符串的缩进空格数常用的数值有2、4两种相信童鞋们已经在编辑代码的时候有过修改缩进tab
空格数的经历了。
在上文案例中我们没有指定缩进空格数量所以格式化后的JSON
字符串都是没有格式的。
举个例子
let Dog = {
name:'Peter',
age:187,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[
{
name:'little peter01',
age:2,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
},
{
name:'little peter02',
age:3,
gender:'male',
hands:['hand01','hand02','hand03','hand04'],
childs:[]
}
]
}
let dogJson = JSON.stringify(Dog,null,2)
console.log(dogJson)
代码的执行结果
对比本文的第一个案例是不是这样的缩进看起来好看多了呢
自定义toJSON方法
在之前的文章中我们讲到每个对象都有的toString
方法当进行格式转换时会自动调用。和toString
一样对象的toJSON
方法会在序列化的时候调用我们可以通过重写这个方法改变序列化的方式。
例如
let dog = {
name : 'peter',
age:18
}
console.log(JSON.stringify(dog))
dog.toJSON = function(){
return this.age;
}
console.log(JSON.stringify(dog))
代码执行结果
我们可以看到在重写了对象的toJSON
方法后使用stringify
的结果发生了改变。
我们可以根据自己的需要重写toJSON
方法从而达到自己的目的。
JSON.parse
上文讲到了如何使用JSON.stringify
把对象转为JSON
格式的字符串这里就详细介绍如何把JSON
字符串转为对象。
语法
let obj = JSON.parse(str,[reviver])
-
str 要解析的
JSON
字符串。 -
reviver 可选的函数
function(key,value)
该函数将为每个(key, value)
对调用并可以对值进行转换。
例如
let str_arr = '[1,2,3]'//数组字符串
let arr = JSON.parse(str_arr)
console.log(typeof arr)
代码执行结果
对于复杂的嵌套对象
let str_obj = `{
"name": "Peter",
"age": 187,
"gender": "male",
"hands": [
"hand01",
"hand02",
"hand03",
"hand04"
],
"childs": [
{
"name": "little peter01",
"age": 2,
"gender": "male",
"hands": [
"hand01",
"hand02",
"hand03",
"hand04"
],
"childs": []
},
{
"name": "little peter02",
"age": 3,
"gender": "male",
"hands": [
"hand01",
"hand02",
"hand03",
"hand04"
],
"childs": []
}
]
}`
let obj = JSON.parse(str_obj)
console.log(obj.name)
代码执行结果
注意
JSON
不支持注释在JSON
中添加注释时错误的行为有一种名为JSON5的格式可以有不加引号的键、允许注释但是这是独立的库补上官方标准。
常规的
JSON
格式严格这样是为了保证数据的可靠、快速解析算法
使用reviver
既然JSON.parse
能够直接转字符串为对象为啥还要再搞reviver
呢
场景举例
如果我们有一个对象字符串如下
// title: (meetup title), date: (meetup date)
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
现在我们要将它转为对象存在什么问题呢
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let obj = JSON.parse(str)
obj.date.getDate();//Error
代码执行结果如下
造成这种结果的原因是date
属性被转为了字符串而不是Date
对象。
这个时候就需要我们使用reviver
函数将date
转为Date
对象
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let obj = JSON.parse(str,function(key,value){
if(key=='date')return new Date(value)
return value
})
obj.date.getDate();
代码执行效果
顺便说一下这也适用于嵌套对象
let schedule = `{
"meetups": [
{"title":"Conference","date":"2017-11-30T12:00:00.000Z"},
{"title":"Birthday","date":"2017-04-18T12:00:00.000Z"}
]
}`;
schedule = JSON.parse(schedule, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
alert( schedule.meetups[1].date.getDate() ); // 正常运行了
总结
- JSON是一种数据格式有独立的标准和大多数编程语言的支持
- JSON支持Object、array、string、number、boolean和null
- JSON.stringify
- JSON.parse