记录在红宝石书上看到关于JSON的知识
JSON是一种数据格式,不是一种编程语言
JSON的语法可以表示以下三种类型的值:
- 简单值:字符串、数值、布尔值和null。但JSON不支持JavaScript中的特殊值undefined
例如:JSON表示字符串的方式:"Hello world!";JSON表示数组为 666 的方式:666 - 对象:对象作为一种复杂数据类型,表示的是一组无序的键值对。而每个键值对中的值可以是简单值,也可以是复杂数据类型的值
例如:JSON表示对象的方式: { "name": "Mashy", "age": 24, "hobby": [ "Music", "football" ] } - 数组:数组也是一种复杂数据类型,表示的是一组有序的值的列表,可以通过数值索引来访问其中的值。数组的值也可以是任意类型——简单值、对象和数组
例如:JSON表示对象的方式: [ { "name": "zhangsan", "age": 22, "hobby": [ "Music", "football" ] }, { "name": "lisi", "age": 25, "hobby": [ "Music", "football" ] } ]
注意:
- JSON字符串必须使用双引号(单引号会导致语法错误)
- JSON对象的属性必须使用双引号
- 同一个对象中绝对不应该出现两个同名的属性
JSON序列化和解析
JSON对象有两个方法(ECMAScript 5):
- stringify():将JavaScript对象序列化为JSON字符串
- parse():将JSON字符串解析为原生JavaScript值
JSON序列化:stringify()
该方法接受三个参数:
- 要序列化的JavaScript对象
- 过滤器(可以是一个数组,也可以是一个函数)
- 选项(表示是否在JSON字符串中保留缩进)
注意:后两个参数是用于指定以不同的方式序列化JavaScript对象
第一个参数:要序列化的JavaScript对象(结合到第二、第三个参数中)
第二个参数:过滤器(可以是一个数组,也可以是一个函数)
假如第二个参数是数组,那么JSON.stringify()的结果中将包含数组中列出的属性。
例如:返回标题和年份
var book1= {
"title": "书名",
"authors": ["zhangsan", "lisi"],
"edition": 1,
"year": 2020
}
var jsonText1 = JSON.stringify(book1, ["title","year"]);
console.log(jsonText1); // "{"title":"书名","year":2020}"假如第二个参数是函数,传入的函数接受两个参数:属性(键)名和属性值。
注意:属性(键)名只能是字符串。
例如:将作者名用 "," 分隔开,年份改为 2021,删除属性 "edition",其他不变
var jsonText2 = JSON.stringify(book1, function(key, value){ switch(key){
case "authors":
return value.join(",");
case "year":
return 2021;
case "edition":
return undefined; // 通过返回undefined,删除该属性
default: // 一定要提供default项返回传入的值,以便其他值能正常出现在结果中
return value;
}
});
console.log(jsonText2); // "{"title":"书名","authors":"zhangsan,lisi","year":2021}"第三个参数:选项(表示是否在JSON字符串中保留缩进)
作用:控制结果中的缩进和空白符(最大缩进长度为10,超过10个则只出现前10个)
如果第三个参数是数值,则表示每个级别缩进的空格数
例如:要在每个级别缩进6个空格
var jsonText3 = JSON.stringify(book1, null, 6);
console.log(jsonText3)
输出:
"{
"title": "书名",
"authors": [
"zhangsan",
"lisi"
],
"edition": 1,
"year": 2020
}"如果第三个参数是一个字符串,则这个字符串将在JSON字符串中被用作缩进字符(不再使用空格缩进)
例如:使用字符串 "#_#" 缩进JSON字符串
var jsonText4 = JSON.stringify(book1, null, "#_#");
console.log(jsonText4)
输出:
"{
#_#"title": "书名",
#_#"authors": [
#_##_#"zhangsan",
#_##_#"lisi"
#_#],
#_#"edition": 1,
#_#"year": 2020
}"另外,JSON.stringify()有时不能满足对某些对象进行自定义序列化的需求。在这些情况下,可以给对象定义toJSON()方法,反馈其自身的JSON数据格式。
可以给任意对象添加toJSON()方法:
var book2= {
"title": "书名",
"authors": ["zhangsan", "lisi"],
"edition": 1,
"year": 2020,
toJSON: function(){
return this.title;
}
}
var jsonText5 = JSON.stringify(book2)
// 序列化之后,执行toJSON()方法返回相应数据
console.log(jsonText5) // ""书名""注意:toJSON()方法作为函数过滤器的补充。
总结:假如将一个对象传入JSON.stringify(),序列化该对象的顺序如下:
- 如果存在toJSON()方法而且能通过它取得有效的值,则调用方法。否则,返回对象本身。
- 如果提供第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
- 对第(2)步返回的每个值进行相应的序列化。
- 如果提供第三个参数,执行相应 的序列化。
JSON解析选项:parse()
该方法接受两个参数:
- 要序列化的JavaScript对象
- 函数(在每个键值对上调用)
第一个参数:要序列化的JavaScript对象(结合到第二中)
第二个参数:函数
该函数接受两个参数:键和值。而且都需要返回一个值。
例如:将对象book3中的标题 "书名" 改为 "书名改变了",其他不变
var book3= {
"title": "书名",
"authors": ["zhangsan", "lisi"],
"edition": 1,
"year": 2020
}
// 序列化
var jsontext6 = JSON.stringify(book3)
console.log(jsontext6)
// "{"title":"书名","authors":["zhangsan","lisi"],"edition":1,"year":2020}"
var changeBookTitle = JSON.parse(jsontext6,function(key, value){
if(key === 'title'){
return "书名改变了";
}else{
return value;
}
})
console.log(JSON.stringify(changeBookTitle))
// "{"title":"书名改变了","authors":["zhangsan","lisi"],"edition":1,"year":2020}"总结
ECMAScript 5定义了一个原生的JSON对象,可以用来将对象序列化为JSON字符串或者将JSON数据解析为JavaScript对象。JSON.stringify()和JSON.parse()方法分别用来实现上述两项功能。这两个方法都有一些选项,通过他们可以改变过滤的方式,或者改变序列化的过程。
原生的JSON对象得到了很多浏览器的支持:IE8+、Firefox 3.5+、Safari 4+、Opera 10.5 和Chrome。