原生JSON对象及兼容问题的解决

我们在使用JSON数据时遇到最多的操作是对JSON格式的数据进行序列化和反序列化操作,在这里我想介绍下什么是JSON数据,JS原生的JSON对象提供的支持及浏览器兼容的问题。

 

1、什么是JSON

 

http://json.org/中是这样介绍JSON:

 

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScript(ECMA-262标准第三版)的一个子集。采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。

JSON采用key/value的形式来表示数据,其中使用“{}”表示对象,而“[]”则表示数组,详细的语法可以参考json.org

 

JSON对象:{"name":"LiLei","age":19,"sex":"male"}
JSON数组:[
             {"name":"LiLei","age":19,"sex":"male"},
             {"name":"HanMei","age":18,"sex":"famale"}
           ]

 

就web开发来讲,JSON数据有三个好处:

 

简洁,方便前台数据操作 - 与XML相比,JSON的分隔符仅限于引号、冒号、逗号、大括号和中括号,并且没有闭合标签的要求,这使得JSON结构更加的简洁。

体积小,传输快。

易用性 - 由于JSON的语法本身就是JavaScript的一个子集,因此对于一个JSON结构几乎不需要额外的解析和查找,可以像使用原生JavaScript对象那样去使用JSON,而XML则需要通过DOM解析来访问。

 

因此,JSON在当前的Web开发用中使用的越来越广泛。其中最常用的两个操作是序列化和反序列化。目前,很多JavaScript库提供都提供了对着两个操作的支持,不过随着ECMA起草了JSON序列化和反序列化的相关标准后,各大浏览器也相应的增加了对JSON的原生支持。

 

2、原生JSON对象

 

目前支持原生JSON对象的浏览器包括:IE8、Firefox3.5以及Chrome3.0/4.0。原生的JSON对象是一个只包括parse方法与stringify方法的纯粹的对象,用于解析和构建JSON文本。

2.1、 JSON.parse(text [ , reviver ] )

 

parse方法的作用是进行反序列化,即将一个符合JSON语法的字符串解析成一个JavaScript对象。该方法可以接受两个参数text与reviver,其中reviver是可选的。text是需要反序列化的字符串,reviver则是一个可选的函数,在反序列化的过程中,每当解析到对象的一个属性时都会将key和value作为参数传递给reviver并执行,之后将返回的结果作为当前key对应值(如果解析的是数组则传递的是当前元素的索引以及元素本身)。如果返回的是undefined则会在解析后的对象中删除对应的属性。具体的使用参见下面的代码:

//简单对象
var str = '{"name":"LiLei","age":19,"sex":"male"}';
var obj = JSON.parse(str);
alert(obj.name);  //LiLei
   
var obj2 = JSON.parse(str,function(k,v){
       if(k == "name"){
           return "HanMeiMei";
       }
       return v;
});
alert(obj2.name);  //HanMeiMei
 
//数组
var str = '[{"name":"LiLei","age":19,"sex":"male"},'+
              '{"name":"Lucy","age":17,"sex":"female"}]';
var obj = JSON.parse(str);
alert(obj[0].name);// LiLei
alert(obj[1].name);//Lucy
   
var obj2 = JSON.parse(str,function(k,v){
    if(k == "name"){
         return "HanMeiMei";
     }
     return v;
});
alert(obj2[0].name); //HanMeiMei
alert(obj2[1].name); //HanMeiMei
//复杂对象
var str = '{"class":"javascript",'+
    '"teacher":{"name":"HanMeiMei","age":28,"sex":"female"},'+
    '"students":[{"name":"LiLei","age":19,"sex":"male"},'+
              '{"name":"Lucy","age":17,"sex":"female"}]}';
var obj = JSON.parse(str);
alert(obj.teacher.name); // HanMeiMei
alert(obj.students[0].name); //LiLei
   
var obj2 = JSON.parse(str,function(k,v){
     if(k == "teacher"){
         v.name = "Poly";
     }
     return v;
});
alert(obj2.teacher.name);  // Poly
alert(obj2.students[0].name); // LiLei
alert(obj2.students[1].name); // Lucy

 

  注意:使用JSON.parse的时候,对象的每个属性都必须用双引号括起来,否则会抛出异常;

 

var str = '{company:"kedacom"}';
var json = JSON.parse(str);  //解析出现异常
var str2 = "{'company':'kedacom'}";
var json2 = JSON.parse(str2);  //解析出现异常

2.2、JSON.stringify(value [ , replacer [ , space ] ] )

stringify方法的作用是进行序列化,即将一个JavaScript对象序列化成JSON结构的字符串。该方法最多可以包含3个参数:

value - 需要序列化的JavaScript对象。

replacer - 可选,可以是函数或者数组,

    如果是函数,则用于过滤序列化的结果。在序列化的执行过程中,每当遍历到对象的一个属性时,都会将属性的key和value传递给replacer并执行,并将执行结果作为该属性的值。

    如果是一个数组,则必须保证数组中的每个元素都是字符串,该数组参数用于指定value中需要进行序列化的属性,如果是对数组进行序列化则会忽略数组形式的replacer参数。

    在使用函数作为replacer时需要注意的是,由于replacer返回的内容仍然会执行序列化,因此如果是返回对象则层次不要太深,不然很容易出“堆栈溢出”的异常,此外如果返回的是undefined则属性会被直接删除掉,而不会出现在字符串中。

       space - 可选,可以是数字或字符串。用于格式化输出,使输出的JSON字符串更易于阅读,这在需要人工检查时非常的有用。如果是数字则表示每一级缩进的空格数,如果是字符串则表示每一级缩进都使用该字符串。使用示例:

     1)只有一个参数的情况下:

 

var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student);
document.write(student);  // [object Object]
document.write(json);
// {"name":"LiLei","age":"30","location":"China"}

 

    2)第二个参数存在,并且是函数

var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,function(k,v){
        if(k == "name"){ return "poly"; }
        return v;
});
document.write(json);
//{"name":"poly","age":30,"location":"China"}
 
var students = ["LiLei","poly","hanmeimei"];
var json = JSON.stringify(students, function (key,value) {
    return value.toString().toUpperCase();
 });
document.write(json);// "LILEI,POLY,HANMEIMEI"

 

    3)第二个参数存在,并且是数组

 

// value是对象,并且replacer为数组时,返回只包含有replacer指定属性的对象
var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"]);
document.write(json); //{"name":"LiLei","location":"China"}
// value是数组,并且replacer为数组时,replace参数被忽略
var students = ["LiLei","poly","hanmeimei"];
var json = JSON.stringify(students);
var json2 = JSON.stringify(students, ["0","2"]);
document.write(json); // ["LiLei","poly","hanmeimei"]
document.write(json2); //["LiLei","poly","hanmeimei"]

 

 

   4)第三个参数存在,并且是数字,表示缩进几个字符,此时最大值为10

 

var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"]); 
alert(json);
var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"],4); 
alert(json);

 
         
 

5)第三个参数存在,并且是转义字符

 

var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"]);
alert(json);
var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"],"\t");
alert(json); 

                 

6)  第三个参数存在,并且仅仅是字符串,就在每行输出值的时候把这些字符串附加上去就OK。最大长度也是10个字符

 

var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"]);
alert(json);
var student = {"name":"LiLei","age":30,"location":"China"};
var json = JSON.stringify(student,["name","location"],"kedacom");
alert(json);

                       

 

3、原生JSON的的浏览器兼容

 

目前支持原生JSON对象的浏览器包括:IE8(S)、Firefox3.5以及Chrome3.0/4.0,对于更低版本的浏览器支持在网络上又很多的解决方案,目前使用最为广泛和成熟的解决方案是在项目中引入json.js库,该扩展库是由大师Douglas Crockford扩展实现(有兴趣的童靴可以读下源码),在最近的一次更新中可以看到如下建议,json.js文件应该使用被最新的json2.js替换。

       

/*
    json.js
    2013-05-26

    Public Domain

    No warranty expressed or implied. Use at your own risk.

    This file has been superceded by http://www.JSON.org/json2.js

    See http://www.JSON.org/js.html
*/

 

https://github.com/douglascrockford/JSON-js可以下载到json.js和json2.js两个文件。

下面就通过在IE6中引入json2.js进行一个简单测试:

 

//没有引入json2.js库的版本
<!DOCTYPE HTML>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script>
if(JSON){
    var student = {"name":"LiLei","age":30,"location":"China"};
    var s = JSON.stringify(student,["name","location"]);
    alert(s);
}else{
    alert("不支持JSON对象");
}
</script>
</head><body></body></html>

 

执行报错:

 
          
 

引入json2.js,代码如下:

……
<script src="json2.js" type="text/javascript"></script>
…… 

          执行结果:

 
                                    
 

4、小结

 

认识javascript也不短的时间了,一直不知道原生JSON对象的存在,知道最近想着从头整理下自己的javascript知识,才知道它的存在,惭愧啊惭愧啊。于是乎,在网上找了些资料,并结合一些例子,希望能给童靴们一些帮助。

 

5、参考

 

http://technet.microsoft.com/zh-cn/sysinternals/cc836459(v=vs.94)

http://json.org/

https://github.com/douglascrockford/JSON-js