JavaScript语言基础(13)JSON轻量级数据格式

172 阅读5分钟

JSON可以直接传给eval()而不需要创建DOM。

把JSON当成一种数据格式,而不是编程语言。

JSON不属于JavaScript,它们只是拥有相同的语法而已。

JSON也不是只能在JavaScript中使用,它是一种通用数据格式,很多语言都有解析和序列化JSON的内置能力。

所有浏览器都已经原生支持全局JSON对象。

语法

JSON语法支持表示3种类型的值:

  1. 简单值:字符串、数值、布尔值和null可以在JSON中出现。特殊值undefined不可以
  2. 对象:第一种复杂数据类型,对象表示有序键/值对。每个值可以是简单值,也可以是复杂类型。
  3. 数组:第二种复杂数据类型,数组的值可以是任意类型,包括简单值、对象,甚至其他数组。

JSON没有变量、函数或对象实例的概念,JSON的所有记号都只为表示结构化数据,只是借用了JS的语法,千万别与JS语言混淆。

简单值

JavaScript字符串与JSON字符串的主要区别是,JSON字符串必须使用双引号(单引号会导致语法错误)。

"Hello world!!" 布尔值和null本身也是有效的JSON值,不过在实践中,更多使用JSON表示比较复杂的数据结构,其中会包含简单值。

对象

JavaScript中的对象字面量:

let person  = {
	name : "CLN",
	age : 21
};

而用JSON表示相同对象的语法是:

{
	"name""CLN",
	"age"21
}

JSON中的对象必须使用双引号把属性名包围起来。JSON主要有两处不同,第一是没有声明变量(JSON中没有变量),第二是最后没有分号(此处不是JS语句,因此不需要)。

属性的值可以是简单值或复杂数据类型值,后者可以在对象中再嵌入对象,比如:

{
	"name""CLN",
	"age"21,
	"school":{
		"name""Nanqiang College",
		"location""Taibei"
	}
}

同一个对象不允许出现两个相同的属性。

数组

JavaScript数组:

let values = [21, "idol", true]; 在JSON中可以使用类似语法表示相同的数组: [21, "idol", true] 数组和对象可以组合使用,以表示更加复杂的数据结构,比如:

[
	{
		"title""Learn about JavaScript",
		"authors":[
			"Nikcjoa Zakad",
			"Matt Fsfds"
		],
		"year"2018
	},
	{
		"title""Learn about JavaWeb",
		"authors":[
			"John Huwdm"
		],
		"year"2019
	}
]

解析与序列化

JSON的迅速流行,主要因为JSON可以直接被解析成可用的JavaScript对象

JSON出现之后就迅速成为了Web服务的事实序列化标准。

JSON对象

JSON对象有两个方法:

stringify()

将JavaScript序列化为JSON字符串。 默认情况下,JSON.stringify()会输出不包含空格或缩进的JSON字符串。

parse()

将JSON解析为原生JavaScript值。 JSON字符串可以直接传给JSON.parse(),然后得到相应的JavaScript值。 若传入的JSON字符串无效,则会导致抛出错误。

序列化选项

JSON.stringify()方法除了要序列化的对象,还可以接收两个参数:

  • 第一个参数是过滤器,可以是数组或函数;
  • 第二个参数是用于缩进结果JSON字符串的选项。
  1. 过滤结果 若第二个参数是一个数组,则此方法返回的结果只包含数组中列出的对象属性。
let book = {
	title : "Learn about JavaScript",
	authors : [
		"Nikcjoa Zakad",
		"Matt Fsfds"
	],
	edition : 4,
	year : 2019
};
let jsonText = JSON.stringify(book, ["title", "edition"]);
// JSON字符串结果
// { "title": "Learn about JavaScript", "edition" : 4 }

若第二个参数是一个函数,提供的函数接收两个参数:属性名(key)和属性值(value)。 这个key始终是字符串,只是在值不属于某个键/值对时回是空字符串。

返回的值就是相应key应包含的结果。返回undefined会导致属性被忽略

let jsonText = JSON.stringify(book, (key, value) => {
	switch(key){
		case "authors" :
			return value.join(",")
		case "year" :
			return 5000;
		case "edition" :
			return undefined;
		default :			// 一定要提供默认返回值,以便返回其他属性传入的值
			return value;
	}
});

第一次调用这个函数,实际上都会传入空字符串key,值是book对象,返回JSON字符串如下:

{ "title": "Learn about JavaScript","authors" : "Nikcjoa Zakad Matt Fsfds", "year" : 5000 }

  1. 字符串缩进 JSON.stringify()方法的第三个参数控制缩进和空格。 在这个参数为数值时,表示每一级缩进的空格数。
let jsonText = JSON.stringify(book, null, 4);
// 得到的结果如下
{ 
	"title": "Learn about JavaScript",
	"authors" : [
		"Nikcjoa Zakad",
		" Matt Fsfds"
	]
	"edition" : 4,
	"year" : 5000 
}

如果缩进参数是一个字符串而非数值,则JSON字符串就会使用这个字符串来缩进。 可以设置缩进字符为Tab或任意字符。

let jsonText = JSON.stringify(book, null, “--”);
// 得到的结果如下
{ 
--"title": "Learn about JavaScript",
--"authors" : [
----"Nikcjoa Zakad",
----" Matt Fsfds"
--]
--"edition" : 4,
--"year" : 5000 
}
  1. toJSON()方法 有时,对象需要在JSON.stringify()之上自定义JSON序列化。 此时,可以在要序列化的对象中添加toJSON()方法,序列化时会基于这个方法返回适当的JSON表示。
let book = {
	title : "Learn about JavaScript",
	authors : [
		"Nikcjoa Zakad",
		"Matt Fsfds"
	],
	edition : 4,
	year : 2019,
	toJSON:function(){
		return this.title;
	}
};
let jsonText = JSON.stringify(book);

toJSON()方法可以返回任意序列化值。 如果对象被嵌入在另一个对象中,返回undefined会导致值变成null;或者如果是顶级对象,则本身就是undefined。

箭头函数不能用来定义toJSON()方法,因为箭头函数词法作用域是全局作用域,在这种情况下不合适。

toJSON()方法可以与过滤函数一起使用。

解析选项

JSON.parse()方法也可接收一个额外的参数,这个函数会针对每个键/值对都调用一次。为区别于传给JSON.stringify()的起过滤作用的替代函数,这个函数被称为还原函数

如果还原函数返回undefined,则结果中就会删除相应的键。 如果返回了其他任何值,则该值会成为相应键的值插入到结果中。

还原函数经常被用于把日期字符串转换为Date对象。如:

let book = {
	title : "Learn about JavaScript",
	authors : [
		"Nikcjoa Zakad",
		"Matt Fsfds"
	],
	edition : 4,
	year : 2019,
	releaseDate:new Date(2017, 11, 1)
};
let jsonText = JSON.stringify(book);
let bookCopy = JSON.parse(jsonText,
	(key, value) => key == "releaseDate" ? new Date(value) : value);
alert(bookCopy.releaseDate.getFullYear());