JSON是什么
JSON,全称是 JavaScript Object Notation,即 JavaScript对象标记法。
JSON 是一种语法,用来序列化对象、数组、数值、字符串、布尔值和 null,基于JS,但是JSON并不是JS的子集
JSON字符串:一种传输数据的格式,本质是字符串
注意:JSON字符串属性名称必须是双引号括起来的字符串;最后一个属性后不能有逗号
JSON的方法
- JSON.stringify()
- JSON.parse()
JSON.stringify(value,replacer,space)
定义:将一个JS对象或值转换为JSON字符串,返回JSON字符串
参数1:要被转换的对象或值
参数2:数组或函数,对序列化的每个属性进行处理,可选
参数3:指定缩进用的字符串,用于美化输出,数字代表多少个空格(1-10),字符串代表该字符串作为缩进,可选,默认没有空格
JSON.stringify([undefined,function test() {},Symbol(""),{ a: 1 },]);
//'[null,null,null,{"a":1}]'
replacer参数
定义:数组或函数格式,对序列化的每个属性进行处理,可选
数组格式 包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中
JSON.stringify({ a: 1, b: 2 }, ["a"]);//'{"a":1}'
函数格式
每个属性都会经过该函数的转换和处理,会按照最顶层属性开始往里,最终达到里层
注意:当遍历到顶层时,传入的形参1会是空字符串 ‘’,形参2是被修改完成的对象,所以得返回该对象
var res = JSON.stringify({ a: 1, b: 2 }, function (prop, v) {
if (prop === "") {
return v;
}
console.log(prop, v);
return v + 1;
});
console.log(res); //'{"a":2,"b":3}'
space参数
定义:用来控制结果字符串里面的间距,数字代表多少个空格(1-10),字符串代表该字符串作为缩进,可选,默认没有空格
常用 \t 换行符
// 使用'\t'制表符
JSON.stringify({ a: 1, b: 2 }, null, "\t");
{
"a": 1,
"b": 2
}
存在的几个特征
- Boolean | Number | String 类型自动会转换为对应原始值
// Boolean对象
let temp =JSON.stringify(new Boolean(1))
console.log(typeof temp) // string
console.log(typeof JSON.parse(temp)) // boolean
// Number对象
let temp =JSON.stringify(new Number(1))
console.log(typeof temp)// string
console.log(typeof JSON.parse(temp))// number
// String对象
let temp =JSON.stringify(new String(1))
console.log(typeof temp)// string
console.log(typeof JSON.parse(temp))// string
- undefined、任意函数、symbol,这三种类型在非数组对象中会被忽略, 在数组中转换成null,在单个值时转换为 undefined
数组对象中 :>> undefined、任意函数、symbol,这三种类型转换为 “null”
// 数组中
let test = () => {};
let arr = [new String(1),test,Symbol("1"),undefined,null];
let temp = JSON.stringify(arr)
console.log(temp);// '["1",null,null,null,null]'
console.log(JSON.parse(temp));// [1,null,null,null,null]
非数组对象中 :>> undefined、任意函数、symbol,这三种类型会被忽略
// 非数组对象中
let obj = {
a: new Number(1),
b: ()=>{},
c: Symbol(1),
d:undefined,
e:null
}
let temp =JSON.stringify(obj)
console.log(temp);// '{"a":1,"e":null}'
console.log(JSON.parse(temp));// { a: 1, e: null }
单个值时:>> undefined、任意函数、symbol,这三种类型转换为 undefined
// 单个值时,当前因为parse需要json格式对象,这样是没意义的
let temp =JSON.stringify(Symbol(1))
console.log(temp)// 'undefined'
let temp1 =JSON.stringify(()=>1)
console.log(temp1) // 'undefined'
- 不可枚举属性会被忽略,数组中不会被忽略
let obj = {
a: new Number(1),
}
Object.defineProperty(obj, "b", {
value: '1',
configurable: false, // 可配置性,默认为false
enumerable: false, // 可枚举性,默认为false
writable: false, // 可重写性,默认为false
});
let temp =JSON.stringify(obj)
console.log(temp)// '{ a: 1 }'
console.log(JSON.parse(temp))// { a: 1 }
- 如果对象属性通过 get 方式返回对象本身,即循环引用,该属性会被忽略
let obj = {
a: new Number(1),
b:'1'
}
Object.defineProperty(obj, "b", {
get(v){
return v
}
});
let temp =JSON.stringify(obj)
console.log(temp)// '{ a: 1 }'
console.log(JSON.parse(temp))// { a: 1 }
封装stringify
class L {
stringify(tar) {// JSON.stringify
// 1.Boolean | Number | String 类型自动会转换为对应原始值
// 2.undefined、任意函数、symbol,这三种类型在非数组对象中会被忽略,在数组中转换成null,在单个值时转换为 undefined
// 3.不可枚举属性会被忽略,数组中不会被忽略
// 4.如果对象属性通过 get 方式返回对象本身,即循环引用,该属性会被忽略
var type = typeof tar;
if (type !== "object") {
if (/undefined|function|symbol/.test(type)) {
return String(undefined);
}
return String(tar);
} else if (tar === null) {
return "null";
} else if (tar.constructor === Array) {// 数组
let json = [];
for (var i = 0; i < tar.length; i++) {
var v = tar[i];
var type1 = typeof v;
if (/undefined|function|symbol/.test(type1) || v === null) {
v = "null";
} else if (/string/.test(type1) || v instanceof String) {
v = '"' + v + '"';
console.log(v);
} else {
v = this.stringify(v);
}
json.push(String(v));
}
return "[" + json.join() + "]";
} else {// 非数组对象
var json = [];
if (tar instanceof Number || tar instanceof Boolean || tar instanceof String) {
return String(tar);
}
for (var k in tar) {
var v = tar[k];
var type2 = typeof v;
if (/undefined|function|symbol/.test(type2)) {
continue;
} else if (v === null) {
v = "null";
} else if (/string/.test(type2) || tar instanceof String) {
v = '"' + v + '"';
} else {
v = this.stringify(v);
}
json.push('"' + k + '":' + String(v));
}
return "{" + json.join() + "}";
}
}
}
JSON.parse(text, reviver)
定义:用来解析JSON字符串,返回油字符串描述的对象或值
参数1:被解析的JSON字符串
参数2:转换器,用来修改生成的对象,可选
var res = JSON.parse('{"a":1,"b":2}', function (prop, v) {
if (prop === "") {
console.log(v,'顶层')
return v;
}
console.log(prop);
console.log(this);
return v +1;
});
/*
a
{ a: 1, b: 2 }
b
{ a: 2, b: 2 }
{ a: 2, b: 3 } 顶层
*/
console.log(res);// {a: 2, b: 3}
reviver参数
定义:用来修改生成的对象,会按照最里层属性开始往外,最终达到顶层
形参1:当前对象属性名
形参2:当前对象属性值
注意:当遍历到顶层时,传入的形参1会是空字符串 ‘’,形参2是被修改完成的对象,所以得返回该对象
JSON.parse('{"p": 5}', function (k, v) {
if(k === '') return v; // 如果到了最顶层,则直接返回属性值,这个是最后指向的
return v * 2; // 否则将属性值变为原来的 2 倍
}); // { p: 10 }
JSON的异常
开发过程中,常常遇到这个错误,这是JSON数据格式不对,得找JSON.parse的参数,找寻具体错误
封装 parse
方式1:使用 eval,存在xss危险(跨站脚本攻击)
class L {
parse(tar) {//存在xss漏洞(跨站脚本攻击)
return eval("(" + tar + ")");
}
}
方式2:使用Function
class L {
parse2(tar){//使用Function
return (new Function('return' + tar))()
}
}
方式3:递归,请参考上文