二十分钟读懂JSON

关于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文档且从中提取数据优点更为明显。

  1. 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值