浏览器们的原生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.
safari4也支持了,这个原生的JSON,应该比json.js快很多了,呵呵
有原生的多好,可惜偶还得支持ie6呢。