关于JSON(JavaScript Object Notation,JavaScript对象表示法),最重要的理解就是它是一种数据格式,不是一种编程语言,它虽然与JS有相同的语法形式,但它并不从属于JS,而且,不只是JS才能使用JSON,很多编程语言都有针对JSON的解析器和序列化器。
一、语法
JSON语法可表示为以下三种类型的值:
- 简单值:使用与JS相同的语法,可在JSON中表示字符串、数值、布尔值、和null。但JSON不支持JS中的特殊值undefined。
- 对象:复杂数据类型,表示一组无序的键值对,在每个键值对中的值可以是简单值,也可以是复杂数据类型的值。
- 数组:复杂数据类型,表示一对有序的值的列表,可通过数据的索引来访问其中的值。数组的值也可以是任意类型——简单值、对象或数组。
JSON不支持变量、函数或对象实例。
1、简单值
例:"Hello World!"//JSON字符串(必须用双引号,单引号会导致语法错误。)
2、对象:与JS对象字面量不同,JSON对象没有声明变量且末尾没有分号。对象的属性必须加引号,对象的属性必须加引号,对象的属性必须加引号,重要的事情说三遍,例:
{
"name":"Mike",
"age":19,
"school":{
"name":"Merrimack College",
"location":"North Andover,MA"
}
}
上例中虽然有两个”name”属性,但由于他们分别属于不同的对象,因此没有问题。不过,同一个对象中不可以出现同名属性。
3、数组:注意JSON数组没有变量和分号,对象数组结合科构成更复杂的数据集合。
二、解析与序列化
JSON流行有一个很重要的原因就是可以把JSON数据解析为有用的JavaScript对象,此点相比XML数据结构解析成DOM文档且从中提取数据优点更为明显。
- JSON对象
早期JSON解析器基本上就是使用JavaScript的eval()函数。由于JSON是JavaScript语法的子集,因此eval()函数可以解析、解释并返回JavaScript对象和数组。在旧版本中,使用eval()对JSON数据结构求值存在风险,可以使用shim。
JSON对象有两个方法:stringify()和parse(),前者用于把JavaScript对象序列化为JSON字符串,后者用于把JSON字符串解析为原生JavaScript值。如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSON Object Example</title>
</head>
<body>
<p>stringify()和parse()</p>
<script type="text/javascript">
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book);
alert(jsonText);
var bookCopy = JSON.parse(jsonText);
alert(bookCopy.title);
</script>
</body>
</html>
默认情况下, JSON.stringify()输出的JSON字符串不包含任何空格字符或缩进,注意虽然book与bookCopy具有相同的属性,但是它们是两个独立的、没有任何关系的对象。如果传给JSON.parse()的字符串不是有效的JSON,该方法就会抛出错误。
2.序列化选项
JSON.stringify()除了要序列化的JavaScript对象外,还可以接受另外两个参数用于指定以不同的方式序列化JavaScript对象,第一个参数是个过滤器,可以是数组也可以是函数;第二个参数是一个选项,表示是否在JSON字符串中保留缩进。
2.1. 过滤结果
如果过滤器参数是数组,那么 JSON.stringify()的结果将只包含数组中列出的属性。如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSON Stringify Example</title>
</head>
<body>
<p>如果过滤器参数是数组,那么 JSON.stringify()的结果将只包含数组中列出的属性。</p>
<script type="text/javascript">
var book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book, ["title", "edition"]);
alert(jsonText);
</script>
</body>
</html>
如果过滤器参数是函数,传入的函数接收两个参数,属性名和属性值,根据属性名可以知道应该如何处理要序列化的对象中的属性。属性名只能是字符串,而在值并非键值对结构的值时,键名可以是空字符串。为了改变序列化对象的结果,函数返回的值就是相应键的值。不过如果函数返回了undefined,那么相应的属性会被忽略。如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSON Stringify Example</title>
</head>
<body>
<p>过滤器参数是函数</p>
<script type="text/javascript">
var book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book, function(key, value){
switch(key){
case "authors":
return value.join(",")
case "year":
return 5000;
case "edition":
return undefined;
default:
return value;
}
});
alert(jsonText);
</script>
</body>
</html>
2.2. 字符串缩进
如果JSON.stringify()方法的第三个参数是数值,则表示每个级别缩进的空格数。如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSON Stringify Example</title>
</head>
<body>
<p>如果JSON.stringify()方法的第三个参数是数值,则表示每个级别缩进的空格数。</p>
<script type="text/javascript">
var book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book, null, 4);
alert(jsonText);
</script>
</body>
</html>
不知道大家有没有发现,JSON.stringify()也在结果字符串中插入了换行符,注意缩进字符串最长为10,所有大于10的值都会自动转换为10。
如果缩进参数是一个字符串而非数值,则这个字符串将在JSON字符串中被用作缩进符。如:
var jsonText = JSON.stringify(book, null, "--");
2.3. toJSON()方法
有时JSON.stringify()还是不能满足对某些对象进行自定义序列化的需求,此时可以给对象定义toJSON()方法,返回其自身的JSON数据格式。原生Date对象有一个toJSON()方法,能够将JavaScript的Date对象自动转换成ISO 8601字符串(与在Date对象上调用toISOString()的结果完全一样)。可以对任何对象添加toJSON()方法,如:
<!DOCTYPE html>
<html>
<head>
<title>JSON Stringify Example</title>
</head>
<body>
<p>toJSON</p>
<script type="text/javascript">
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011,
toJSON: function(){
return this.title;
}
};
var jsonText = JSON.stringify(book);
alert(jsonText);
</script>
</body>
</html>
3、解析选项
JSON.parse()方法也可以接第二个参数,该参数是一个函数,将在每个键值对上调用,被称为还原函数。若还原函数返回undefined,则表示要从结果中删除相应的键;若返回其他值,则将该值插入到结果中。将日期字符串转换为Date对象时,经常要用到还原函数,如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSON Parse Example</title>
</head>
<body>
<p>还原函数</p>
<script type="text/javascript">
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011,
releaseDate: new Date(2011, 11, 1)
};
var jsonText = JSON.stringify(book);
alert(jsonText);
var bookCopy = JSON.parse(jsonText, function(key, value){
if (key == "releaseDate"){
return new Date(value);
} else {
return value;
}
});
alert(bookCopy.releaseDate.getFullYear());
</script>
</body>
</html>