一、JSON概念
JSON (JavaScript Object Notation) 一种简单的数据格式,是一种是轻量级的文本数据交换格式。在js中会解析成对象。
JSON 解析器和 JSON 库支持许多不同的编程语言,所以它在不同的语言中,有不同的名字。
二、JSON的结构
JSON建构于两种结构:对象和数组。
- “名称/值”对的集合。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
- 值的有序列表。在大部分语言中,它被理解为数组(array)。
对象结构以 { 大括号开始,以 } 大括号结束。中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如代码。
其中关键字是字符串,而值可以是字符串,数值,true,false,null,对象或数组
数组结构以 [ 开始,以 ] 结束。中间由0或多个以”,”分隔的值列表组成,语法结构如代码。
三、字符串、JSON字符串、JSON对象
字符串:这个很好解释,指使用“”双引号或’’单引号包括的字符。例如:var comStr = ‘this is string’;
json字符串:指的是符合json格式要求的js字符串。例如:var jsonStr = “{StudentID:‘100’,Name:‘tmac’,Hometown:‘usa’}”;
json对象:指符合json格式要求的js对象。例如:var jsonObj = { StudentID: “100”, Name: “tmac”, Hometown: “usa” };
四、JSON与JS对象的对比
区别 | JSON | JavaScript |
含义 | 仅仅是一种数据格式 | 类的实例 |
传输 | 可以跨平台数据传输,速度快 | 不能传输 |
表现 | 1. 键值对的方式,属性必须加双引号 2. 值不可以是方法函数、undefined以及 | 1. NAN键值对方式,属性不加引号 2. 值可以是函数、对象、字符串、数字、boolean 等 |
相互转换 | JSON.parse(str) | JSON.stringify(obj) |
五、JSON.parse()
作用:将json字符串转换成json对象。
语法:JSON. parse(text[,reviver]).
参数:
- text 必须;一个有效的json字符串。
- reviver 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
返回值:一个对象或数组。
var text = '{ "name":"test", "initDate":"2021-05-01", "age": 18 }';
var obj = JSON.parse(text, function (key, value) {
if (key == "initDate") {
return new Date(value);
} else {
return value;
}});
obj = {
age: 18
initDate: Sat May 01 2021 08:00:00 GMT+0800 (中国标准时间) {}
name: "test"
}
六、JSON.stringify()
作用:将json对象转换成json字符串。
语法:JSON.stringify(value [, replacer] [, space])
参数:
- value 必须;通常为对象或数组。
- replacer 可选,用于转换结果的函数或者数组。
- space 可选。向返回值 JSON 文本添加缩进、空格和换行符以使其更易于读取。
返回值:一个包含JSON文本的字符串。
第一个参数
如果只传一个参数,那么就是正常的将值(对象或者数组)转换成JSON字符串。
obj = {
age: 18
initDate: "2021-05-01",
name: "test"
}
JSON.stringify(obj)
"{"name":"test","initDate":"2021-05-01T00:00:00.000Z","age":18}"
第二个参数
第二个参数作用就是过滤,可以为一个过滤函数,也可以是一个数组。
当参数是数组,将以数组中的元素作为键值返回一个新的JSON对象
obj = {
age: 18,
initDate: "2021-05-01",
name: 'test'
}
JSON.stringify(obj, ['name', 'age', 'sex']);
// age 由于不在列表里,所以没被序列化
"{"name":"test","age":18}"
也可以传递一个函数到第二个参数中,改变它的返回值
obj = {
age: 18,
initDate: "2021-05-01",
name: 'test'
}
JSON.stringify(obj, (key, value) => {
if (key === 'name') {
return 'name';
}
return value;
});
"{"name":"name","initDate":"2021-05-01T00:00:00.000Z","age":18}"
第三个参数
用来控制结果字符串里面的间距。
JSON.stringify的第三个参数,用于控制字符的间距
- 参数类型为数字,缩进的字符宽度,每一级别会比上一级别缩进多这个数字值的空格(最多10个空格)
- 参数类型为字符串,则是将占位符改为字符串,每一级别会比上一级别多缩进用该字符串(或该字符串的前十个字符)。
- 如果不加第三个参数,输出会只占一行
obj = {
name: 'test',
other: {
age: 18,
initDate: '2021-05-01'
}
};
JSON.stringify(obj)
{"name":"test","other":{"age":18,"initDate":"2021-05-01"}}
JSON.stringify(obj, null, 4)
{
"name": "test",
"other": {
"age": 18,
"initDate": "2021-05-01"
}
}
JSON.stringify(secondItem, null,'?');
{
?"name": "test",
?"other": {
??"age": 18,
??"initDate": "2021-05-01"
?}
}
toJSON方法
可以自定义stringify返回的内容
如果一个被序列化的对象拥有 toJSON 方法,那么该 toJSON 方法就会覆盖该对象默认的序列化行为
这里的toJSON必须是一个function,如果是别的类型就不行了,比如之前提到的数组。
obj = {
age: 18,
initDate: "2021-05-01",
name: 'test',
toJSON: function() {
return {
name: this.name,
other: {
initDate: this.initDate,
age: this.age
}
}
}
}
JSON.stringify(obj);
"{"name":"test","other":{"initDate":"2021-05-01","age":18}}"
优先级
- 首先检查被转化的对象是否存在toJSON的方法,如果存在则调用该方法,否则,按照默认顺序序列化
- 如果传入第二个参数,则用这个函数过滤器。传入过滤器的值是第一步返回的值。
- 对第二步返回的每个值进行相应的序列化
- 如果提供了第三个参数,执行相应的格式化。
obj = {
name: 'test',
age: 18,
initDate: '2021-05-01',
toJSON() {
return {
name: this.name,
age: this.age,
initDate: '2022'
};
}
};
JSON.stringify(obj, ['age', 'initDate']);
{"age":18,"initDate":"2022"}
数据格式要求
实际上并不是所有的JSON数据都能被序列化
- 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
JSON.stringify({x: 5, y: 6});
// '{"x":5,"y":6}' 或者 '{"y":6,"x":5}' 都可能
- 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
- undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
obj = {"boolean": true, "number": 2, "string": 'abc'}
JSON.stringify(obj);
// "{"boolean":true,"number":2,"string":"abc"}"
obj = {"undefined":undefined,"func":function(){},"symbol":Symbol("")};
JSON.stringify(obj);
//"{}"
var arr = [undefined,function(){},Symbol("")];
JSON.stringify(arr); //[null,null,null]
- 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
JSON.stringify({[Symbol("foo")]: "foo"}); //'{}'
- 不可枚举的属性会被忽略
JSON.stringify( Object.create(null, { x: { value: 'x', enumerable: false }, y: { value: 'y', enumerable: true } }) );
// '{"y":"y"}'