JSON的自定义序列化和解析

来源:互联网 发布:网络家装行业发展趋势 编辑:程序博客网 时间:2024/05/01 21:18

JSON的语法表示可以是以下三种类型的值:
简单值:使用于JavaScript相同的语法,可以在JSON中表示字符串、数值、布尔值和null.但JSON不支持Javascript中的特殊值undefined.
对象:对象作为一种复杂数据类型,表示的是一组无序的键值对。而每个键值对可以是简单值,也可以是复杂数据类型的值。
数组:数组是一种复杂数据类型,表示一组有序的值的列表,可以通过数字索引来访问其中的值。数组的值也可以是任意类型——简单值、对象和数组。

简单值:
Javascript和JSON字符串最大的区别在于:JSON字符串中必须使用双引号(单引号会导致语法错误)
简单值与JS的并不不同,如5,”Hello”

对象:
JSON对象与JS字面量(对象)略有不同。
JS中:

var trav = {    destination: "China",    number: 5};

在JSON中必须为属性加上引号,如下:

{    "destination": "China",    "number": 5}

当然JS中也可以这样来定义对象。JSON对象与JS对象字面量相比,有三点不同:
1、没有声明变量
2、没有末尾的分号
3、对象的属性必须加双引号
属性的值可以是简单值,也可以是复杂类型值:

{    "destination": "China",    "number": 5,    "fee":{        "Shanghai":1000,        "Nanjing":800    }}

数组:
JSON数组采用的就是JS中的数组字面量形式,如下:
[“blue”, “red”, “yellow”]
同样,JSON数组也没有变量和分号。

把数组和对象结合起来,可以构成更复杂的数据集合,如:

[        {            "id": 1,            "name":"Nick",            "parents":["William", "Lucy"]        },        {            "id": 2,            "name":"Devin",            "parents":["Sherlock", "Chir"]        },        {            "id": 2,            "name":"Abby",            "parents":["Abbott", "Diana"]        }]

数组和对象通常是JSON的最外层形式。

解析与序列化

JSON之所以流行,拥有与JS类似的语法并不是全部原因,更重要的一个原因是其解析方便。

JSON对象:
由于JSON是JS语法的分集,因此eval()函数可以解析、解释并返回JS对象和数组。但是使用eval()来解析,存在风险,肯能会执行一些恶意代码.
JSON对象有两个方法:stringify()和parse(),在最简单的情况下,这两个方法分别用于将JS对象序列化为JSON字符串;将JSON字符串解析为原生的JS对象。

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013    };var jsonText = JSON.stringify(book);

默认情况下,JSON.stringfy()输出的JSON字符串不包含任何人空格字符或缩进,因此jsonText中的字符串如下所示:

{"title":"Professional Javascript","authors":["zzh","dff"],"edition":2,"year":2013}

在序列化JS对象时,所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为undefined的任何属性也会被跳过。结果中最终都是值为有效JSON数据类型的实例属性。
比如,上面的book定义如下:

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013,        releaseDate: function(){            console.log("aaa");        }    };

序列化的JSON字符串与前面一样,因为函数会被有意忽略掉。

将JSON字符串传递给JSON.parse()就可以得到相应的JS值。

var book2 = JSON.parse(jsonText);

序列化选型
json.stringify()除了要序列化的JS对象外,还能接收另外两个参数,这两个参数用于指定以不同的方式序列化JS对象。第一个参数是个过滤器,可以是一个数组,也可以是一个函数。第二个参数是一个选项,表示是否在JSON字符串中保持缩进。
过滤器
如果过滤器参数是个数组,那么JSON.stringify()的结果中只包含数组中列出的属性。

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013    };        var jsonText = JSON.stringify(book,["authors"]);    console.log(jsonText); //{"authors":["zzh","dff"]}

如果过滤器参数是个函数,此函数接收两个参数:属性名(键)和属性值。根据键名处理要序列化的对星座的属性。
为了返回序列化对象的结果,函数返回的值就是相应键的值,不过,需要注意的是,如果值为undefined,那么相应的属性会被忽略.

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013    };    var jsonText = JSON.stringify(book, function(key,value){        switch(key){                        case "title":                return "Javascript";            case "authors":                return "Yvette";            case "edition":                return undefined;            default:                return value;                    }        }); console.log(jsonText);//{"title":"Javascript","authors":"Yvette","year":2013}

“edition”返回的值是undefined,相当于删除了”edition”属性。
一定要提供defalut项,这样不需要特殊处理的属性,才能被正常返回。

字符串缩进
JSON.stringify()方法的第三个参数用于控制结果中的缩进和空白字符。如果这个参数是一个数值,那它表示的是每个级别缩进的空格数;如果缩进参数是一个字符串而非数值,那么这个字符串将在JSON字符串中被用作缩进字符。无论是缩进空格还是缩进字符,其最大长度都不能超过10,如果超过,也只会出现前10个。

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013    };    var jsonText = JSON.stringify(book, null, 4)console.log(jsonText);/*{    "title": "Professional Javascript",    "authors": [        "zzh",        "dff"    ],    "edition": 2,    "year": 2013}*/
var jsonText = JSON.stringify(book, function(key,value){        switch(key){            case "authors":                return "Yvette";            case "edition":                return undefined;            default:                return value;                    }        }, " - - ")console.log(jsonText);/*{ - - "title": "Professional Javascript", - - "authors": "Yvette", - - "year": 2013}*/

尽管结果显示正确,但是控制台上会报错,Uncaught SyntaxError。

toJSON()方法
有时候,JSON.stringify()还不能满足对某些对象进行自定义序列化的需求,在这种情况下,可以给对象定义toJSON()方法,返回其自身的JSON数据格式.

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013,        toJSON:function(){            return this.title        }    };    var jsonText = JSON.stringify(book);console.log(jsonText) ;//"Professional Javascript"

toJSON()可以作为函数过滤器的补充,假设把一个对象传入JSON.stringify(),序列化该对象的顺序如下:
1、如果存在toJSON()方法而且能够通过它取得有效的值,则调用该方法。否则,返回对象本身。
2、如果提供了第二个参数,应用这个函数过滤器.传入函数过滤器的值是第一步返回的值。
3、对第二步返回的每个值进行相应的序列化。
4、如果提供了第三个参数,执行相应的格式化。

解析选项

JSON.parse()方法也可以接收另一个参数,该参数是一个函数,将在每个键值对上调用。为了区别JSON.stringify()接收的替换(过滤)函数(replacer),这个函数被称为还原函数(receiver).这个函数接收的参数同样是一个键和一个值。
如果还原函数返回undefined,则表示要从结果中删除相应的键;如果返回其他值,则将该值插入到结果中.如:

var book = {        title: "Professional Javascript",        authors:["zzh","dff"],        edition:2,        year:2013,        releaseDate: new Date(2011, 11, 2)    };        var jsonText = JSON.stringify(book);    console.log(jsonText)    var bookCopy = JSON.parse(jsonText, function(key, value){        if (key == "releaseDate")        {            return new Date(value)                    }else{            return value;        }    });    console.log(bookCopy);

将releaseDate转换为了Date对象。

0 0
原创粉丝点击