1. JSON.parse
JSON.parse
用于解析 JSON 格式的字符串,将 JSON 转化成 JavaScript 对象。
JSON.parse(JSON字符串, 处理函数);
第一个参数是要转换成对象的 JSON 字符串,第二个参数可以不传递/
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }';var user = JSON.parse(str);console.log(user);
传递给 JSON.parse 方法的字符串要符合 JSON 标准,否则会报错。
第二个参数非常有趣,传入的是一个函数,这个函数会在每个 JSON 属性被解析的时候调用,同时会传递属性名和属性值给函数作为参数,传入参数的返回值会作为当前遍历到的属性的新值。
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }';var user = JSON.parse(str, function(key, value) {
console.log(key, value);
return value;});
可以发现上述例子打印的最后以想,属性名是可以空字符串,属性值是解析完的结果。
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }';var user = JSON.parse(str, function(key, value) {
console.log(key, value);
return '强行修改值';});
观察输出后,可以发现所有属性都被遍历了,并且赋值成功,但是最终 user
也变成了返回的字符串。
这是因为当解析完成后,传入的函数会被最后调用一次,传递进来的值就是最终 JSON.parse 的返回值,所以对其修改后,会影响到的最终结果。
var str = '{ "name": "baba", "age": 12, "info": { "locate": "浙江" } }';var user = JSON.parse(str, function(key, value) {
console.log(key, value);
if (key === '') {
return value;
}
return '强行修改值';});
对传递过来的属性名为空字符串 ''
进行单独处理即可避免这种特殊情况。
2. JSON.stringify
JSON.stringify 用于将JavaScript对象转换成 JSON 格式的字符串。
JSON.stringify(JavaScript对象, 处理函数, 缩进空格字符数量);
第二个参数可以是个函数,也可以是个数组。
如果是函数,则每一个属性在处理的时候就被调用这个函数,同时属性名和属性值作为参数传递给这个函数,并且函数的返回值作为这个处理属性的值。
如果是数组,则只有属性名在数组中的属性才会被处理,不传递则默认处理整个对象。
如果第二个参数传递 null ,也就是不做特殊处理,在使用到第三个参数的时候,第二个参数会传递 null 。
第三个参数可以传递数字,也可以传递字符串,传递了这个参数会对结果做格式化,具有一定的格式,参数的值决定格式化的样式。
如果是数字,则使用对应长度的空格来缩进,长度 1 到 10 ,比 1 小则表示不缩进。
如果是字符串,则会使用传入的字符串进行缩进,传入的字符串长度超过 10 ,则会截取前 10 个作为缩进字符。
var user = {
name: '小明',
age: 14,
skill: ['HTML', 'Java'],};var json = JSON.stringify(user);console.log(json);
第二个参数用起来和 parse 方法的第二个参数类似。
var user = {
name: '小明',
age: 14,
skill: ['HTML', 'Java'],};var json = JSON.stringify(user, function(key, value) {
console.log(key, vlue);
return value;});console.log(json);
根据上述例子可以看到,先输出的属性为空字符串,属性值为被处理对象,所以如果不想操作原对象,需要做特殊处理。
var user = {
name: '小明',
age: 14,
skill: ['HTML', 'Java'],};var json = JSON.stringify(user, function(key, value) {
if (key === '') {
return value;
}
return '我是处理过的值';});console.log(json);
这样处理后,最终处理完的 JSON 字符串的属性值都是函数的返回值了。
var obj = [
{
path: '/',
component: 'function() {}',
children: [
{
path: 'note',
component: 'function() {}',
},
{
path: 'friends',
component: 'function() {}',
}
]
},
{
path: '*',
component: 'function() {}',
}];var json1 = JSON.stringify(obj, null);var json2 = JSON.stringify(obj, null, 2);var json3 = JSON.stringify(obj, null, '*-*');console.log(json1); console.log(json2); console.log(json3);
- 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
传入参数后就会将处理后的 JSON 字符串进行格式化,缩进部分根据传入的参数值决定。
3. 其他注意点
3.1 深拷贝
可以配合 JSON 的两个方法,对对象进行深拷贝。
var obj = {prop: 'value'};var newObj = JSON.parse(JSON.stringify(obj));newObj.prop = 'new value';console.log(obj);console.log(newObj);
根据结果可以看到新的对象修改,没有影响到原对象,两者之间不存在引用关系。
3.2 序列化规则
使用 JSON.stringify 有些内置规则。
- 如果对象中存在包装对象,则在转换过程中会变成原始值。
var obj = {
string: new String('A promise is a promise.'),
number: new Number(996),};var result = JSON.stringify(obj);console.log(result);
- 如果转换的对象或者对象下的属性存在 toJSON 方法,那么这个方法的返回值会作为转换结果。
var user = {
nickname: 'joker',
toJSON: function() {
return 'hahahahahahaha';
},}var result = JSON.stringify(user);console.log(result);
var obj = {
b: 2,
c: 3,
a: 1,};
"{"a":1,"b":2,"c":3}""{"a":1,"c":3,"b":2}""{"b":2,"a":1,"c":3}""{"b":2,"c":3,"a":1}""{"c":3,"b":2,"a":1}""{"c":3,"a":1,"b":2}"
- undefined、ES6 中的 symbol 值、函数在转换过程中都会被忽略,当然函数如果具有 toJSON 方法依然会优先选择 toJSON 方法的结果。
var fn = function() {};fn.toJSON = function() {return '我是函数'};var result = JSON.stringify({
a: fn,
b: Symbol(1),
c: undefined,
d: function() {},});console.log(result);
var obj1 = {
prop1: 1,};var obj2 = {
prop1: 1,};obj1.prop2 = obj2;obj2.prop2 = obj1;JSON.stringify(obj1);
- 在 ES6 中,symbol 可以作为对象的属性值,但在处理的时候都会被忽略。
var symbol = Symbol();var obj = {
prop1: 'value1',
[symbol]: 'value2',};console.log(obj);var result = JSON.stringify(obj);console.log(result);
- null、正负 Infinity、NaN 在序列化时都会被当作 null 。
var obj = {
null: null,
infinity1: +Infinity,
infinity2: -Infinity,
NaN: NaN,};var result = JSON.stringify(obj);console.log(result);
4. 小结
JSON 几乎是目前前后端交互最常用的数据格式,所以 JSON 对象使用的频率也很高。
在使用 JSON.parse
反序列化的时候,如果 JSON 格式不符合规范,是会报错的,日常开发中建议封装一层 JSON 的方法,将错误集中处理,方便定位与上报错误。