app开发定制37.JavaScript对象与JSON格式的转换,JSON.stringify、JSON.parse方法的使用方法和注意事项


文章目录


JSON处理

JSONJavaScript Object Notation)是JavaScriptapp开发定制表达值和对象的通用数据格式,app开发定制其本质就是符合一定规app开发定制范的字符串。由于JSONapp开发定制的优良特性,app开发定制非常容易和其他语言进app开发定制行数据交换,app开发定制尤其在前后端交互方面。app开发定制即使我们前端使用JavaScript,后端使用Java/PHP/Pythonapp开发定制同样可以使用JSONapp开发定制格式的数据轻松交换。

JSON.stringify

JavaScriptapp开发定制为我们提供了简单的方法可以实现对象和字符串之间的转化。

  1. JSON.stringify将对象转为JSON字符串;
  2. JSON.parseJSON字符串转为对象;

例如,我们把一个对象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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

代码的执行效果:

可见,使用JSON.stringify(obj)方法会返回该对象objJSON字符串数据,这个转换的过程可以称作JSON编码(JSON-encoded)序列化(serialized),亦或者编组化(marshalled)。当对象转为普通的字符串后,我们就可以以普通数据的格式存储、传递这些数据。

如果我们把这些字符串写入数据库,就相当于把JavaScript对象存进了数据库。

注意:

  1. JSON编码的对象统一使用双引号,没有单引号和反引号;
  2. 对象的属性名也用双引号,这是强制的;

JSON已经发展成为了独立的数据规范,因此归属于JavaScript语言本身的非数据属性会被JSON.stringify跳过。

包括:

  1. 对象方法;
  2. Symbol类型
  3. undefined的属性
let user = {    sayHello(){//函数被忽略        console.log('hello world');    },    [Symbol('id')]:996996,//Symbol被忽略    val:undefined//undefined值被忽略}console.log(JSON.stringify(user))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码执行效果:

可以看到,里面啥也没有。

stringify的限制

并非所有的对象都能转为JSON格式,如果对象之间存在循环引用,就会导致转换失败。

let father = {}let son = {}father.son = sonson.father = fatherJSON.stringify(father)
  • 1
  • 2
  • 3
  • 4
  • 5

代码执行结果:

这里出现错误的原因就是存在对象间的循环引用,Father引用了Son,而Son又反过来引用了Father

排除和替换

如果我们只希望将对象的个别属性转为JSON格式,或者摆出循环应用中的属性,应该怎么做呢?

JSON.stringify已经为我们提供了解决方法:

let  json = JSON.stringify(obj[,replacer,space])
  • 1

参数解读:

  1. obj:要编码的对象
  2. replacer:要编码的属性数组或者映射函数function(k,v)
  3. 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']))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

代码的执行结果如下:

如果我们在第二个参数传入一个数组,那么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']))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码执行结果:

但是,还存在一个问题,如果对象属性特别多,可能数组就会非常长,代码也会很冗长。

这种情况下就需要使用映射函数

映射函数

我们可以创建一个函数,代替数组作为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;}))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

代码执行结果如下:

由于值为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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

代码的执行结果:

对比本文的第一个案例,是不是这样的缩进看起来好看多了呢?

自定义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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

代码执行结果:

我们可以看到,在重写了对象的toJSON方法后,使用stringify的结果发生了改变。

我们可以根据自己的需要重写toJSON方法,从而达到自己的目的。

JSON.parse

上文讲到了如何使用JSON.stringify把对象转为JSON格式的字符串,这里就详细介绍如何把JSON字符串转为对象。

语法:

let obj = JSON.parse(str,[reviver])
  • 1
  1. str 要解析的 JSON 字符串。

  2. reviver 可选的函数 function(key,value),该函数将为每个 (key, value) 对调用,并可以对值进行转换。

例如:

let str_arr = '[1,2,3]'//数组字符串let arr = JSON.parse(str_arr)console.log(typeof arr)
  • 1
  • 2
  • 3

代码执行结果:

对于复杂的嵌套对象:

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

代码执行结果:

注意:JSON不支持注释,在JSON中添加注释时错误的行为

有一种名为的格式,可以有不加引号的键、允许注释,但是这是独立的库,补上官方标准。

常规的JSON格式严格,这样是为了保证数据的可靠、快速解析算法

使用reviver

既然JSON.parse能够直接转字符串为对象,为啥还要再搞reviver呢?

场景举例:

如果我们有一个对象字符串如下:

// title: (meetup title), date: (meetup date)let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
  • 1
  • 2

现在我们要将它转为对象,存在什么问题呢?

let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';let obj = JSON.parse(str)obj.date.getDate();//Error
  • 1
  • 2
  • 3

代码执行结果如下:

造成这种结果的原因是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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

代码执行效果:

顺便说一下,这也适用于嵌套对象:

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() ); // 正常运行了!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

总结

  1. JSON是一种数据格式,有独立的标准和大多数编程语言的支持
  2. JSON支持Object、array、string、number、boolean和null
  3. JSON.stringify
  4. JSON.parse
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发