JSON
简介
- JSON是JavaScript Object Notation(JavaScript对象示意法)的缩写
- JSON是一种数据格式, 而不是一种编程言语, 用来示意构造化数据
- JSON是JavaScript的一个严厉子集
- JSON并不从属于JavaScript, 许多编程言语都可以用JSON数据格式
语法
JSON语法可以示意以下三种范例的值:
- 简朴值: 字符串/数值/布尔值/
null
, 然则不支持undefined
- 对象
- 数组
JSON不支持变量/函数/对象实例
简朴值
字符串
"Hello JSON"
数字
66
布尔值
true
null
null
对象
和JavaScript对照来看 ->
- JavaScript示意对象
键值对的键可以加引号也可以不加, 假如加引号, 可以加单引号也可以加双引号
// 最常见就这么写
const obj1 = {
foo: 'bar',
num: 66,
status: true
};
// 这么写也oconstet obj2 = {
'foo': 'bar',
'num': 66,
'status': true
};
// 这么写也ok
const obj1 = {
"foo": "bar",
"num": 66,
"status": true
};
- JSON示意对象
键值对的键必需加双引号(手写JSON时肯定要注重)
对象没有变量声明, 由于JSON根本就没有变量的观点(它不是一个编程言语)
末端没有分号
{
"foo": "bar",
"num": 66,
"status": true
}
和JavaScript类似, 对象可以嵌套对象
{
"foo": "bar",
"num": 66,
"status": true,
"baz": {
"num": 88
}
}
注, 同名属性可以在差别的对象中, 然则不能涌现在同一个对象中
数组
和JavaScript对照来看 ->
- JavaScript示意数组
let arr = ['hello', 66, true];
- JSON示意数组
一样没有变量声明和末端的分号, 同时注重字符串简朴值要加双引号
["hello", 66, true]
数组和对象结合起来可以组成庞杂的鸠合, 比方students.json文件中多是如许婶儿的
[
{
"name": "小明",
"age": 10,
"score": {
"math": 88,
"english": 99
}
},
{
"name": "小强",
"age": 11,
"score": {
"math": 98,
"english": 96
}
}
]
看到以上同JavaScript的差别之处, 我们可以晓得为何说JSON是JavaScript的一个严厉子集了吧
JSON序列化与剖析
基础用法
ECMAScript5定义了全局对象JSON, 用来剖析JSON字符串
简朴来讲, JSON对象有两个要领
-
JSON.stringify()
: 把JavaScript对象序列化为JSON字符串 -
JSON.parse()
: 把JSON字符串剖析为原生JavaScript值
const book = {
name: 'Learn JavaScript in One Day',
pages: 1
};
const jsonText = JSON.stringify(book); // 序列化
// "{"name":"Learn JavaScript in One Day","pages":1}"
const parseText = JSON.parse(jsonText); // 剖析
// {name: "Learn JavaScript in One Day", pages: 1}
默许情况下, JSON.stringify()
输出的JSON字符串不包括任何空格字符或缩进(是不是是给我们供应了一种将去除数据中无用的空缺和缩进的要领呢).
在序列化JavaScript对象时, 一切函数及原型成员都邑被故意疏忽, 不体现在效果中. 别的, 值为undefined
的任何属性也都邑被跳过. 效果中终究都是值为有用JSON数据范例的实例属性.
const book = {
name: 'Learn JavaScript in One Day',
pages: 1,
foo: undefined
};
const jsonText = JSON.stringify(book); // 序列化
// "{"name":"Learn JavaScript in One Day","pages":1}"
// foo的值为undefined, 所被疏忽掉了
将JSON字符串直接传递给JSON.parse()
就可以获得响应的JavaScript值.
JSON.parse()
就是JSON.stringify()
的逆向操纵. 将一个JavaScript值序列化以后再剖析JSON.parse(JSON.stringify(foo))
和本来的foo
险些一样.
注重, 为何说是险些一样呢?
- 假如foo是一个对象或数组, 那末这么一折腾就变成了两个差别的对象或数组了;
这就供应了一种克隆对象和数组的要领😆
- 假如foo是一个对象, 而且foo中有值为
undefined
的属性, 那末在序列化的历程当中它会被筛掉; - 假如foo是一个数组, 而且其中有
undefined
的项, 那末在序列化历程当中undefined
的项会变成null
; - 假如foo是一个简朴值(数字/布尔值/字符串), 那末这么一折腾效果完整是相称的.
const foo1 = { a: 1 };
JSON.parse(JSON.stringify(foo1)) === foo1; // false
const foo2 = [1, 2];
JSON.parse(JSON.stringify(foo2)) === foo2; // false
const foo3 = { a: 1, b: undefined };
JSON.parse(JSON.stringify(foo3)); // {a: 1}
const foo4 = [1, true, undefined];
JSON.parse(JSON.stringify(foo4)); // [1, true, null]
const foo5 = true;
JSON.parse(JSON.stringify(foo5)) === foo5; // true
假如传给JSON.parse()
的字符串不是有用的JSON, 该要领会抛出毛病.
进阶用法
序列化选项
JSON.stringify()
除了要序列化的JavaScript对象外, 还可以吸收别的两个参数, 这两个参数用于指定以差别的体式格局序列化JavaScript对象.
第一个参数是个过滤器, 可以是一个数组, 也可以是一个函数;
第二个参数是一个选项, 示意是不是在JSON字符串中保存缩进.
1.过滤效果
假如过滤器参数是数组, 那末JSON.stringify()
的效果中将只包括数组中列出的属性
const book = {
name: 'Learn JavaScript in One Day',
pages: 1
};
JSON.stringify(book, ['name']);
// "{"name":"Learn JavaScript in One Day"}"
再看下面的例子🌰:
const stu = {
name: "小明",
age: 10,
score: {
math: 88,
english: 99
}
};
JSON.stringify(stu, ['name', 'score']);
// "{"name":"小明","score":{}}"
注重, 末了效果中score是一个空对象, 那末小明的结果哪儿去了?
彷佛我们的目标是要显现name和score属性, 只去掉age就好了, 然则score对象中咋啥也没有了?
那我们把stu对象从新改改尝尝:
var stu = {
name: "小明",
age: 10,
score: {
math: 88,
english: 99,
name: 'xiuxiu~',
score: 100
}
};
JSON.stringify(stu, ['name', 'score']);
// "{"name":"小明","score":{"name":"xiuxiu~","score":100}}"
这下看邃晓了么, 本来这个过滤是对每一层级的对象都过滤一遍.
假如第二个参数是函数, 行动会稍有差别. 传入的函数吸收两个参数, 属性名(键)和属性值(值). 依据属性名可以晓得应当怎样处置惩罚要序列化的对象中的属性. 属性名只能是字符串, 而在值并不是键值对儿构造的值时, 键名可以是空字符串. 函数返回的值就是响应键的值, 假如函数返回了undefined
, 那末响应的属性会被疏忽.
const stu = {
name: "小明",
age: 10,
score: {
math: 88,
english: 99
}
};
const newStu = JSON.stringify(stu, (key, value) => {
switch(key) {
case 'math':
return 100;
case 'english':
return 100;
default:
return value;
}
});
// "{"name":"小明","age":10,"score":{"math":100,"english":100}}"
// 胜利将小明的结果改成了100分, 哈哈哈~
2.字符串缩进
JSON.stringify()
要领的第三个参数用于掌握效果中的缩进和空缺符. 假如这个参数是一个数值, 那它示意的是每一个级别缩进的空格数.
JSON.stringify()
会在效果字符串中插进去换行符以进步可读性.
最大缩进空格数为10, 一切大于10的值都邑自动转换为10.
const stu = {
name: "小明",
age: 10,
score: {
math: 88,
english: 99
}
};
JSON.stringify(stu, null, 4); // 4个空格的缩进
/* 序列化后的效果
"{
"name": "小明",
"age": 10,
"score": {
"math": 88,
"english": 99
}
}"
*/
假如缩进参数是一个字符串而非数值, 则这个字符串将在JSON字符串中被用作缩进字符(不再运用空格).
缩进字符串最长不能超过10个字符长. 假如字符串长度超过了10个, 效果中将只涌现前10个字符.
JSON.stringify(stu, null, '--');
/* 序列化后的效果
"{
--"name": "小明",
--"age": 10,
--"score": {
----"math": 88,
----"english": 99
--}
}"
*/
3.toJSON
有时候, JSON.stringify()
照样不能满足对某些对象举行自定义序列化的需求. 在这些情况下, 可以给对象定义toJSON()
要领, 返回其自身的JSON数据格式. 原生Date对象有一个toJSON()
要领,可以将JavaScript的Date对象自动转换成ISO8601日期字符串(与在Date对象上挪用toISOString()
的效果完整一样).
JSON.stringify(new Date());
// 序列化后的效果: ""2019-04-08T11:31:05.778Z""
new Date().toJSON();
new Date().toISOString();
// 直接挪用toJSON和toISOString要领一样能获得字符串: "2019-04-08T11:31:44.432Z"
可以让toJSON()
要领返回任何值, 它都能一般事情.
const stu = {
name: "小明",
age: 10,
score: {
math: 88,
english: 99
},
toJSON() {
return this.name;
}
};
JSON.stringify(stu);
// 序列化后的效果: ""小明""
toJSON()
可以作为函数过滤器的补充, 因而明白序列化的内部递次十分重要. 假定把一个对象传入JSON.stringify()
, 序列化该对象的递次以下:
(1) 假如存在toJSON()
要领而且能经由历程它获得有用的值, 则挪用该要领. 不然, 返回对象自身;
(2) 假如供应了第二个参数, 运用这个函数过滤器. 传入函数过滤器的值是第(1)步返回的值;
(3) 对第(2)步返回的每一个值举行响应的序列化;
(4) 假如供应了第三个参数, 实行响应的格式化.
剖析选项
JSON.parse()
要领也可以吸收另一个参数, 该参数是一个函数, 将在每一个键值对儿上挪用. 为了区分 JSON.stringify()
吸收的替代(过滤)函数(replacer), 这个函数被称为复原函数(reviver), 但实际上这两个函数的署名是雷同的——它们都吸收两个参数, 一个键和一个值, 而且都须要返回一个值.
假如复原函数返回undefined
, 则示意要从效果中删除响应的键; 假如返回其他值, 则将该值插进去到效果中.
const stu = {
name: "小明",
age: 10,
score: {
math: 88,
english: 99
}
};
const jsonText = JSON.stringify(stu);
JSON.parse(jsonText, (key, value) => {
if (key === 'name') {
return value + '牛逼了!';
} else {
return value;
}
});
/* 剖析效果
{
age: 10
name: "小明牛逼了!"
score: { math: 88, english: 99 }
}
*/
小结
JSON是一个轻量级的数据格式, 可以简化示意庞杂数据构造的事情量. JSON运用JavaScript语法的子集示意对象、数组、字符串、数值、布尔值和null
.
ECMAScript5定义了一个原生的JSON对象, 可以用来将对象序列化为JSON字符串或许将JSON数据剖析为JavaScript对象. JSON.stringify()
和JSON.parse()
要领离别用来完成上述两项功用. 这两个要领都有一些选项, 经由历程它们可以转变过滤的体式格局, 或许转变序列化的历程.