都知道JSON是一种用来序列化对象、数组、数值、字符串、布尔值、null的数据格式。它基于JavaScript语法,而并非JavaScript的子集。
具体的语法参看MDN
- 对于对象和数组, 属性名一定要使用双引号,最后一个属性后不得有逗号
JSON.parse('{a: 1}') // Uncaught SyntaxError: Unexpected token a in JSON at position 1
JSON.parse('{"a":1,"b":2,}') // Uncaught SyntaxError: Unexpected token } in JSON at position 13
JSON.parse('["a","b",]') // Uncaught SyntaxError: Unexpected token ] in JSON at position 9
- 前导0是被禁止的,小数点后必须要有一位数字
JSON.parse('01') // Uncaught SyntaxError: Unexpected number in JSON at position 1
JSON.parse('1.') // Uncaught SyntaxError: Unexpected end of JSON input
- 只有一些字符会被转义,禁止一些控制字符,字符串必须是双引号
JSON.parse('"\x22"') // Uncaught SyntaxError: Unexpected string in JSON at position 2
JSON.parse('"\n"') // Uncaught SyntaxError: Unexpected token in JSON at position 1
JSON.parse('"\u2028"') // ""
JSON.parse('"\u2030"') // "‰"
JSON有两个常用方法:
stringify(): 用于将js对象序列化
语法
JSON.stringify(value[, replacer[, space]])
value就是要转化成JSON字符串的对象
replacer是过滤器,可以是一个数组,也可以是一个函数
space是表示在JSON字符串中的缩进用的空白字符串,如果这个值是数值则代表有多少个空格(上限是10,大于10会自动转化为10)
关于序列化有六点要注意:
- 对数组对象的属性不能保证以特定顺序出现在序列化后的字符串中
- 布尔值、数字、字符串的包装对象(通过new Boolean(), new Number(), new String()得到的包装对象)在序列化后会自动转化成对应的原始值
- undefined、 任意的函数以及symbol值,若出现在非数组对象的属性值中时,在序列化过程中会被忽略
JSON.stringify({
fn: function(){},
undefined,
}) // "{}"
若出现在数组中,则被转换成null
JSON.stringify([undefined, function fn(){}]) // "[null,null]"
- 正则对象,序列化后转会成{}
let reg = new RegExp('\d')
JSON.stringify({
reg,
}) // '{"reg":{}}'
JSON.stringify([reg, function(){}]) // "[{},null]"
JSON.stringify(reg) // "{}"
- 所有symbol为属性键都会被忽略
JSON.stringify({[Symbol("foo")]: "foo"}) // "{}"
- 不可枚举的属性会被忽略
let obj = {
a: 1
}
Object.defineProperty(obj, 'b', {
value: 2,
enumerable: false
})
JSON.stringify(obj) // '{"a":1}'
replacer参数
- 如果value参数是普通对象而replacer是一个数组,数组的值代表将被序列化成JSON字符串的属性名
JSON.stringify({a: 1, b: 2}, ['a', 'c']) // "{"a":1}"
JSON.stringify({a: 1, b: 2}, ['c']) // "{}"
- 如果value参数是普通对象而replacer是一个函数,函数接受两个参数,根据函数的返回值序列化生成JSON字符串。当replacer返回普通对象,该对象会递归序列化,每一个属性继续调用replacer方法,知道返回的值是符合JSON语法的值(返回函数、undefined等都会被忽略)
JSON.stringify({str: 'str', number: 17, test: null}, (key, value) => {
if (typeof value === 'number') {
return undefined
}
return value
}) // '{"str":"str","test":null}'
toJSON方法
看一个例子
JSON.stringify(new Date()) // '"2017-09-11T17:12:13.939Z"'
date实例原型链中的Date.prototype.toJSON()能够调用Date.prototype.toISOString()方法将date实例转换为ISO 8601 日期字符串。
而任何对象都可以定义一个toJSON方法,当JSON.stringify()序列化某个对象,如果在toJSON()能够返回符合JSON语法的有效值,就调用这个方法,否则返回undefined。
let fn = function(){}
fn.toJSON = function(){
return 1
}
JSON.stringify(fn) // '"1"'
fn.toJSON = function(){
return undefined
}
JSON.stringify(fn) // undefined
有意思的是
let date = new Date()
date.toJSON = function (){
return date
}
JSON.stringify(date) // "{}"
parse(): 用于将JSON字符串解析成js中的原始值或对象或数组
语法
JSON.parse(text[, reviver])
text就是要解析的JSON字符串,如果它不符合JSON语法则会报错。
reviver是函数,接受一个键一个值,并返回一个值。如果返回的值是undefined, 表示从结果中删除相应的键。
JSON.parse('{"p": 5, "str": "string"}', (key, value) =>
typeof value !== 'number'
? value
: undefined
) // {str: "string"}
JSON.parse('{"p": 5, "str": "string"}', (key, value) =>
typeof value === 'number'
? value
: undefined
) // undefined