JSON由来
这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战
在目前的开发中,JSON是一种非常重要的数据格式,它并不是编程语言,而是一种可以在服务器和客户端之间传输的数据格式。
JSON的全称是JavaScript Object Notation(JavaScript对象符号):
- JSON是由Douglas Crockford构想和设计的一种轻量级资料交换格式,算是JavaScript的一个子集;
- 但是虽然JSON被提出来的时候是主要应用JavaScript中,但是目前已经独立于编程语言,可以在各个编程语言中使用
- 很多编程语言都实现了将JSON转成对应模型的方式
目前JSON被使用的场景也越来越多:
- 网络数据的传输JSON数据;
- 项目的某些配置文件
- 非关系型数据库(NoSQL)将json作为存储格式
基本写法
JSON的顶层支持三种类型的值:
-
简单值:数字(Number)、字符串(String,不支持单引号)、布尔类型(Boolean)、null类型(JSON不支持undefined)
-
对象值:由key、value组成,key是字符串类型,并且必须添加双引号,值可以是简单值、对象值、数组值(JSON不支持函数)
-
数组值:数组的值可以是简单值、对象值、数组值
-
JSON中不支持任何形式的注释
-
JSON的数据项如果是最后一个,那么该数据项不可以以逗号进行结尾
[
null,
{
"name": "Klaus",
"age": 23
}
]
序列化
某些情况下我们希望将JavaScript中的复杂类型转化成JSON格式的字符串,这样方便对其进行处理
比如我们希望将一个对象保存到localStorage中,但是如果我们直接存放一个对象,这个对象会被转化成 [object Object] 格式的字符串,并不是我们想要的结果
在ES5中引用了JSON全局对象,该对象有两个常用的方法:
- stringify方法:将JavaScript类型转成对应的JSON字符串
- parse方法:解析JSON字符串,转回对应的JavaScript类型
const user = {
name: 'Klaus',
age: 23
}
// obj -> JSON string--- 序列化
const str = JSON.stringify(user)
console.log(str)
// JSON string -> obj ---- 反序列化(解析)
const obj = JSON.parse(str)
console.log(obj)
JSON方法
stringify
基本使用
const user = {
name: 'Klaus',
age: 23,
friend: {
name: 'Alex',
age: 18
}
}
const str = JSON.stringify(user)
console.log(str)
第二个参数 --- replacer --- 选择性的替换值
const user = {
name: 'Klaus',
age: 23,
friend: {
name: 'Alex',
age: 18
}
}
// 类型1 --- 数组
// 转换后的结果,只要name和age字段,不要friend字段
const str1 = JSON.stringify(user, ['name', 'age'])
console.log(str1) // => {"name":"Klaus","age":23}
// 类型2 --- 函数
// 可以拦截每一个字段,进行自行处理
const str2 = JSON.stringify(user, (key, value) => {
// 如果不指定这个函数,默认值就是直接返回value
// return value
if (key === 'age') {
value += 1
}
return value
})
console.log(str2) // => {"name":"Klaus","age":24,"friend":{"name":"Alex","age":18}}
参数3 --- space --- 需要添加的空格数
const user = {
name: 'Klaus',
age: 23,
friend: {
name: 'Alex',
age: 18
}
}
// 类型1 --- 数字 --- 假设值为n
// 转换后的结果换行,且每个字段前添加n个空格
// 第二个参数如果传递的是null,那么表示的就是使用默认值
const str1 = JSON.stringify(user, null, 2)
console.log(str1)
/*
=>
{
"name": "Klaus",
"age": 23,
"friend": {
"name": "Alex",
"age": 18
}
}
*/
// 类型2 --- 字符串
// 转换后的结果换行,且每个字段前添加传入的字符串
const str2 = JSON.stringify(user, null, '---')
console.log(str2)
/*
=>
{
---"name": "Klaus",
---"age": 23,
---"friend": {
------"name": "Alex",
------"age": 18
---}
}
*/
toJSON
const user = {
name: 'Klaus',
age: 23,
friend: {
name: 'Alex',
age: 18
},
toJSON() {
// 如果一个对象中存在toJSON方法
// 那么在将这个对象转换为JSON字符串的时候
// 会自动去调用该toJSON方法
return '调用了user的toJSON方法'
}
}
console.log(JSON.stringify(user)) // => "调用了user的toJSON方法"
parse
const str = '{"name":"Klaus","age":24,"friend":{"name":"Alex","age":18}}'
// 1. 基本使用
console.log(JSON.parse(str))
// 2. 传入第二个参数 --- 拦截,进行自定义操作
console.log(JSON.parse(str, (key, value) => {
if (key === 'age') {
value -= 1
}
return value
}))
JSON.parse方法返回的对象并不是之前的对象,实际上是对之前的对象进行了一次深拷贝
但是因为JSON并不支持函数这种数据格式,所以使用JSON序列化的方式来进行深拷贝的时候,如果遇到函数的时候是无能为力的
const user = {
name: 'Klaus',
age: 23,
friend: {
name: 'Alex',
age: 18
},
fun() {
console.log('我并不能被深拷贝')
}
}
const newUser = JSON.parse(JSON.stringify(user))
user.friend.name = 'Jhon'
console.log(newUser.friend.name) // => Alex
// 并不存在fun函数
console.log(newUser) // => { name: 'Klaus', age: 23, friend: { name: 'Alex', age: 18 } }