浏览器们的原生JSON对象

一、什么是JSON

JSON是Javascript Object Notation的简写,单从字面上看可以翻译成:Javascript对象标记,在Javascript中可以使用JSON语法来描述一个对象。json.org是如下介绍JSON的:

 

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition – December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。
一个JSON对象看上去大概是这样的:

	{
          "firstName": "cyra",
           "lastName": "richardson",
           "address": {
                "streetAddress": "1 Microsoft way",
                 "city": "Redmond",
                 "state": "WA",
                 "postalCode": 98052
          },
           "phoneNumbers": [
                "425-777-7777",
                 "206-777-7777"
           ]
     }
	

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

JSON的优点大概可以总结为以下2点:

  • 简洁、体积小 – 与XML相比,JSON的分隔符仅限于引号、冒号、逗号、大括号和中括号,并且没有闭合标签的要求,这使得JSON结构更加的简洁,而体积上在表示相同数据量时也往往相对小一些。与此同时,也更加的易于阅读和检查。
  • 易用性 – 由于JSON的语法本身就是Javascript的一个子集,因此对于一个JSON结构几乎不需要额外的解析和查找,可以像使用原生Javascript对象那样去使用JSON,相比之下XML则需要通过DOM解析来访问。

正是由于以上的优点,JSON在当前的Web应用中使用的越来越广泛。而在JSON的使用中,最常用的两个操作是序列化和反序列化。目前,已经有不少Javascript库提供了对这两个操作的支持,不过随着ECMA起草了JSON序列化和反序列化的相关标准,各大浏览器也相应的增加了对JSON的原生支持。

二、原生JSON对象

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

JSON.parse(text [ , reviver ] )

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

		var str = '{"key1":1,"key2":{"key21":2}}';
		var obj = JSON.parse(str,function(k,v){
			if( k == 'key21' ) return 2009;
			return v;
		});
		alert(obj.key2.key21); //输出2009
	

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

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

  • value – 需要序列化的Javascript对象。
  • replacer – 可选,可以是函数或者数组。用于过滤或修改序列化的结果。如果是一个函数,则在序列化的过程中,每当遍历到对象的一个属性时,都会将属性的key和value传递给replacer并执行,并将执行结果作为该属性的值。如果是一个数组,则必须保证数组中的每个元素都是字符串,该数组参数用于指定value中需要进行序列化的属性,如果是对数组进行序列化则会忽略数组形式的replacer参数。在使用函数作为replacer时需要注意的是,由于replacer返回的内容仍然会执行序列化,因此如果是返回对象则层次不要太深,不然很容易出“堆栈溢出”的异常,此外如果返回的是undefined则属性会被直接删除掉,而不会出现在字符串中。
  • space – 可选,可以是数字或字符串。用于格式化输出,使输出的JSON字符串更易于阅读,这在需要人工检查时非常的有用。如果是数字则表示每一级缩进的空格数,如果是字符串则表示每一级缩进都使用该字符串。

具体的使用见下面的例子:

	var obj = {key1:[1,2,3,{key11:[1,2,3,{key111:'hello world'}]}]};
	var objString = JSON.stringify(obj,function(k,v){
		if( k == 'key111' )
			return 'test';
		return v;
	});
	/*
	如果不使用space则objString的值为
	{"key1":[1,2,3,{"key11":[1,2,3,{"key111":"test"}]}]}
	*/
	/*
	如果使用t作为space则结果是下面这样的:
	{
		"key1": [
			1,
			2,
			3,
			{
				"key11": [
					1,
					2,
					3,
					{
						"key111": "test"
					}
				]
			}
		]
	}
	*/

三、原生JSON API的兼容性

由于标准的存在,几大浏览器在API的定义上都保持了一致,不过经过测试还是发现有一些不同点的,罗列如下:

  • 对数学表达式的支持 – 形如“(59+1)*2 / 2 – 1”这样的字符串,在Chrome下parse的结果是59,即Chrome下会将字符串当作表达式进行计算并返回结果,而在IE8与Firefox中则会抛语法错误的异常。
  • 对日期的序列化 – 对于日期对象的序列化,所有浏览器都是按照ISO标准进行的,不过Firefox的序列化会精确到毫秒,而IE与Chrome都精确到秒,例如对日期对象new Date(”December 31, 2009 23:59:59″)的序列化结果,在IE与Chrome下是”2009-12-31T15:59:59Z”,而在Firefox下是”2009-12-31T15:59:59000Z”。
  • 对待undefined – 在ECMA的标准中规定对undefined是不进行序列化的,也就是说如果执行JSON.stringify(undefined)应该返回undefined,而在IE下则会返回字符串的”undefined”,在Firefox与Chrome中均直接返回undefined。
  • Firefox3.5中的Bug – 在Firefox3.5中,当JSON.stringify的replacer参数为函数时将不会起作用,例如:

    		var obj = {key1:[1,2,3,{key11:[1,2,3,{key111:'hello world'}]}]};
    		var objString = JSON.stringify(obj,function(k,v){
    			if( k == 'key111' )
    				return 'new value';
    			return v;
    		});
    		/*正确的结果应该是:'{"key1":[1,2,3,{"key11":[1,2,3,{"key111":"new value"}]}]}'*/
    		/*但是在Firefox3.5中的却是:'{"key1":[1,2,3,{"key11":[1,2,3,{"key111":"hello world"}]}]}',没有产生效果*/
    		

    不过当返回的是undefined时又能够正确的删除属性。

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

2 Comments »

 
 

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">