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和nullJ SON.stringify JSON.parse到此这篇关于JavaScript对象与JSON格式的转换及JSON.stringify和JSON.parse的使用方法的文章就介绍到这了,更多相关JS与JSON格式转换内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
查看更多关于JavaScript对象与JSON格式的转换及JSON.stringify和JSON.parse的使的详细内容...