JSON格式是一种轻量级的用于数据交换的文本格式,不是一种编程语言。
优点:简洁清晰,符合js语法,可以由js引擎直接处理。
JSON对象
JSON对象包含两个方法: 用于解析JSON的parse()
方法以及将对象/值转换为 JSON字符串的 stringify()
方法。除了这两个方法, JSON这个对象本身并没有其他作用,也不能被调用或者作为构造函数调用。
早期JSON解析器基本上使用eval()函数,使用eval()存在风险,可能会执行恶意代码。ES5定义了全局JSON对象,提供了两个静态方法JSON.stringify() 和 JSON.parse();对于较老版本的浏览器还需要使用shim。
JSON流行还有更重要的一点是可以把JSON数据结构解析成javascript对象,与XML要解析成DOM文档从中提取数据极为繁琐相比,JSON简洁清晰的优势就极其明显。
JSON中的对象和javascript对象字面量的区别:
- 没有声明变量,即JSON中没有变量的概念
- 末尾没有分号(因为不是javascript语句)
- 对象的属性必须加双引号
可表示的值类型
- 原始类型:
* 字符串、数字(必须是十进制)、null、布尔值
* 不能使用NaN, Infinity, -Infinity和undefined
- 复杂类型
* 数组或对象,不能是函数、正则表达式对象、日期对象(因为日期对象有toJSON()方法,下面具体介绍)
格式
- 字符串必须用双引号表示,不能使用单引号
- 对象的key必须用双引号表示
- 对象或数组的最后一个成员不可加逗号
序列化方法 JSON.stringify()
1. 参数一:要序列化的值
JSON.stringify()方法用于将一个值转为 JSON 字符串。
JSON.stringify(122) // "122"
JSON.stringify(false) // "false"
JSON.stringify(null) // "null"
JSON.stringify('sina') // ""sina""
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"
对于字符串,转换结果会带双引号
JSON.stringify('sina') === "\"sina\"" // true
对象的属性如果是函数、undefined、XML对象,以及原型成员、不可枚举属性,会被JSON.stringify()过滤。
JSON.stringify({name: undefined}) // "{}"
JSON.stringify({ skill: function() {} }) // "{}"
JSON.stringify([ undefined, function() {} ]) // "[]"
JSON.stringify(/sina/) // "{}"
const obj = { age: 12 }
Object.defineProperty(obj, 'name', {
value: 'jack',
enumerable: false
})
JSON.stringify(obj) // "{"age": 12}"
2. 参数二:过滤器
JSON.stringify()还可以接受第二个参数作为过滤器,该参数可以是数组或函数。
- 如果是数组,则JSON.stringify()的结果中将只包含数组中列出的属性,该方式只对对象有效,对数组无效。
const obj {
name: 'jack',
age: 12,
address: 'sina'
}
JSON.stringify(obj, ['name', 'address']) // "{"name": "jack", "address": "sina"}"
JSON.stringify([1,2,3], [1]) // "[1,2,3]"
- 如果是函数,该函数接收两个参数,key、value,根据key来处理要序列化的对象中的属性值。
const obj {
a: 1,
b: 2,
c: 'sina'
}
JSON.stringify(obj, (key, value) => {
if (typeof key === 'number') return value * 3
return value
})
// "{"a": 3, "b": 6, "c": "sina"}"
需要注意的是,该处理函数会递归所有的key,如:
const obj = {
a: 2,
b: {
c: 3
}
}
JSON.stringify(obj, (key, value) => {
console.log('key: ', key, ' ; value: ', value)
if (typeof key === 'number') return value * 2
return value
})
// key: '' ; value: {a: 2, b: {c: 3}}
// key: a ; value: 2
// key: b ; value: {c: 3}
// key: c ; value: 3
// "{"a":2,"b":{"c":3}}"
以上执行结果,函数被处理了四次,最后是执行结果。 第一次key为空,value是整个对象;第二次key为a,value为2;第三次key为b,value为{c: 3};第四次key为c,value为3。
递归处理中每一次处理的对象,都是前一次返回的值
const obj = {
a: {
b: 2
},
c: 4
}
JSON.stringify(obj, (key, value) => {
if (key === 'a') return {b: 22}
if (typeof value === 'number') return value * 2
return value
})
// "{"a":{"b":44},"c":8}"
如果函数返回undefined,则该属性会被忽略。
const obj = {name: 'jack', age: 12}
JSON.stringify(obj, (key, value) => {
if (typeof value === 'number') return undefined
return value
})
// "{"name": "jack"}"
3. 参数三:字符串缩进
JSON.stringify() 的第三个参数用于控制结果中的缩进和空白符。如果参数是数值,则表示每个级别缩进的空格数。最大缩进10个。还可以是字符串,最长不超过10个字符。
JSON.stringify({age: 12}, null, 2)
"{
"age": 12
}"
JSON.stringify({age: 12}, null, '--')
"{
--"age": 12
}"
toJSON() 方法
有时候JSON.stringify()还不能满足对某些对象进行自定义序列化的需求。在这种情况下可以给对象添加toJSON()方法,返回自定义的数据,忽略对象的其他参数,然后再序列化。原生Date对象有一个toJSON()方法,能够将javascript中的Date对象自动转成ISO 8610日期字符串(与Date对象上调用toString()结果完全一样)
JSON.stringify({
a: 1,
toJSON() {
return {b: 2}
}
})
// "{"b":2}"
JSON.stringify({date: new Date()}) // "{"date":"2019-05-29T07:14:15.035Z"}"
toJSON()的一个应用场景是将正则对象转字符串
RegExp.prototype.toJSON = RegExp.prototype.toString
JSON.stringify(/sina/) // ""/sina/""
解析选项JSON.parse()
JSON.parse() 可以接收另外一个参数,该参数是一个函数,将在每个键值对上调用,与JSON.stringify()过滤器对应,该函数被称为还原函数
如果还原函数返回undefined,则表示将该属性从结果中删除;如果返回其他值,则插入结果中。
在将日期字符串还原时会经常用到还原函数。
const obj = {
date: new Date(),
a: 12,
name: 'jack',
address: 'sina'
}
const jsonText = JSON.stringify(obj)
JSON.parse(jsonText, (key, value) => {
if (key === 'date') return new Date(value)
if (typeof value === 'number') return value * 2
if (key === 'address') return undefined
return value
})
/*
{
a: 24,
date: Wed May 29 2019 15:36:14 GMT+0800 (中国标准时间),
name: "jack"
}
/*
如果传入的字符串不是有效的 JSON 格式,JSON.parse方法将报错。可以将JSON.parse方法放在try...catch代码块中,处理解析错误。
JSON.parse("\"sina\"") // "sina"
JSON.parse('"sina"') // "sina"
JSON.parse("23423") // 23423
try {
JSON.parse("'sian'")
}
catch(e) {
console.log('error')
}
参考:
高级程序设计
MDN
网友评论