引言
一直以来以为JSON就是字符串的一种,但其实是不对的,JSON其实是一种数据格式,有自己的一套语法,并且也不属于Javascript,因为你可以在很多中编程语言中见到他。
JSON的语法
JSON语法支持表示3种类型的值:
类型 | 值 |
---|---|
简单值 | 包括字符串、数值、布尔值和null,但undefined不可以,这个后续会提及 |
对象 | 与js中的对象类似,包含键值对,每个值可以是简单值或者复杂类型 |
数组 | 数组的值也可以是简单值或者复杂类型 |
其中需要注意的点是JSON中的字符串都需要使用双引号包裹,不可以用单引号,这和JS的字符串是有差别的,例如JSON中对象的属性名是需要用双引号括起来的。
JSON对象
序列化
使用JSON.stringify()把一个JS对象序列化成一个JSON字符串,例如:
let book = {
title: 'Professional Javascript',
author: ['Nicholas C. Zakas', 'Matt Frisbie'],
edition: 4,
year: 2017,
printTitle(){
console.log(this.title)
},
meta: undefined
}
console.log(JSON.stringify(book))
//{"title":"Professional Javascript","author":["Nicholas C. Zakas","Matt Frisbie"],"edition":4,"year":2017}
可以看到一个JS对象被序列化成一个JSON的字符串了,而且这个字符串不包含空格和缩进,也不包含函数和原型成员。
另外,如果值为undefined,则该键值对也不会被转化到JSON字符串中去。
过滤
实际上JSON.stringify()这个函数接收3个参数,第一个就是一个JS对象,而第二个是一个过滤器,接收的参数可以是一个数组,也可以是一个函数,可以自由选择需要转化的键值对,例如:
//参数为数组,数组的值是需要转化的键值对
console.log(JSON.stringify(book, ["title", "author"]))
//{"title":"Professional Javascript","author":["Nicholas C. Zakas","Matt Frisbie"]}
//参数为函数,自由度更大,可以自定义返回的内容
console.log(JSON.stringify(book, (key, value) => {
switch(key){
case "author":
return value.join(',')
case "year":
return 5000
case "edition":
return undefined
default:
return value
}
}))
//{"title":"Professional Javascript","author":"Nicholas C. Zakas,Matt Frisbie","year":5000}
缩进
第三个参数就是调整缩进的了,接收一个数值或者字符串,数值代表基础缩进的空格数,字符串(或者字符,制表符等)代表用什么字符串来填充缩进,这两个的目的都是为了方便阅读。
console.log(JSON.stringify(book, null, 4))
/*
{
"title": "Professional Javascript",
"author": [
"Nicholas C. Zakas",
"Matt Frisbie"
],
"edition": 4,
"year": 2017
}
*/
console.log(JSON.stringify(book, null, "--"))//注意如果使用字符串,长度限制为10,多了只会截取前10个字符
/*
{
--"title": "Professional Javascript",
--"author": [
----"Nicholas C. Zakas",
----"Matt Frisbie"
--],
--"edition": 4,
--"year": 2017
}
*/
toJSON()方法
如果我们在定义JS对象的时候,就想好了要转化成JSON字符串,并且想要自定义转化后的结果,那么我们可以在对象中定义一个toJSON方法,那么在序列化的时候就会根据这个方法来进行序列化:
let book = {
title: 'Professional Javascript',
author: ['Nicholas C. Zakas', 'Matt Frisbie'],
toJSON(){
return this.title
}
}
console.log(JSON.stringify(book))
//"Professional Javascript"
这个方法和JSON.stringify()的第二个和第三个参数并不冲突,但有一定的顺序:
let book = {
title: 'Professional Javascript',
author: ['Nicholas C. Zakas', 'Matt Frisbie'],
edition: 4,
year: 2017,
printTitle() {
console.log(this.title)
},
meta: undefined,
toJSON(){
return {
"title": this.title,
"author": this.author
}
}
}
console.log(JSON.stringify(book, ["title"], '--'))
/*
{
--"title": "Professional Javascript"
}
*/
个人感觉和过滤的作用有点重复了,除非不想要存储属性名。
解析选项(反序列化)
没什么好说的,就是将序列化后的JSON字符串还原成JS对象,除了接收JSON字符串之外,同样可以接收一个还原函数(好比序列化中的过滤函数),直接看例子:
let book = {
title: 'Professional Javascript',
author: ['Nicholas C. Zakas', 'Matt Frisbie'],
edition: 4,
year: 2017,
releaseDate: new Date(2017, 11, 1)
}
const JsonText = JSON.stringify(book)
const bookCopy = JSON.parse(JsonText, (key, value) => key == "releaseDate" ? new Date(value) : value)
console.log(bookCopy)
/*
{
title: 'Professional Javascript',
author: [ 'Nicholas C. Zakas', 'Matt Frisbie' ],
edition: 4,
year: 2017,
releaseDate: 2017-11-30T16:00:00.000Z
}
*/
注意上面的日期类型,被序列化后是一个字符串,解析的时候需要重新new Date(value)重新创建一个相同的日期。
以上就是本次学习JSON的全部内容了,学完感觉对JSON的理解清晰了许多。
上述内容参考自《Javascript高级程序设计》第4版,当作一个学习的笔记。