不存在所谓的"JSON对象"!

时间:2022-12-31 00:17:10

英文原文:http://benalman.com/news/2010/03/theres-no-such-thing-as-a-json/

我想给大家澄清一下一个非常普遍的误解,我相信很多JavaScript开发人员都错误地把JavaScript对象字面量(Object Literals)称为JSON对象(JSON Objects),因为他的语法和JSON规范里描述的一样,但是该规范没有明确提到的是JSON只是一个数据交换语言,只有我们将之用在string上下文的时候它才叫JSON。

序列化和反序列化

当两个应用程序/服务器/语言等需要交互通信的时候,他们倾向于使用字符串,因为字符串可以用几乎相同的方式在所有语言中进行解释。复杂的数据结构经常需要用到,并且通过各种类型的花括号、方括号、尖括号或空格来组成,但字符串只是一个有序的字符序列。

为此,我们为了可以将复杂的数据结构描述为字符串,创建了标准的规则和语法。JSON只是其中一种这样的语法,它可以在字符串上下文中描述对象、数组、字符串、数字、Booleans 和 null,可以从应用程序中传递到应用程序,并根据需要进行反序列化。 YAMLXML(甚至请求参数)是另外两种流行的数据交换(或序列化)格式,但是,我们喜欢JSON,谁叫我们是JavaScript开发人员呢!

字面量

引用Mozilla Developer Center里的几句话,供大家参考:

  • 字面量是固定值,而不是变量,让你从“字面上”理解脚本。 (Literals)
  • 字符串字面量是由双引号(”)或单引号(’)包围起来的零个或多个字符组成的。(Strings Literals)
  • 对象字面量是由大括号({})括起来的零个或多个对象的属性名-值对。(Object Literals)

那么,什么时候JSON不是JSON?

JSON是作为一种数据交换格式设计的,它的语法是JavaScript的一个子集。

正因为如此,{ “prop”: “val” } 这样的声明有可能是一个JavaScript对象字面量也有可能是一个JSON字符串,这取决于所使用的上下文,如果它在字符串上下文中被使用(用单引号或双引号包围,或者从文本文件读取)的话,那么它就是一个JSON字符串,如果它在对象字面量上下文中被使用,那么它就是对象字面量。

// 这是JSON字符串
var foo = '{ "prop": "val" }';

// 这是对象字面量
var bar = { "prop": "val" };

另外,请注意,JSON有非常严格的语法,在字符串上下文里 { “prop”: “val” } 是个合法的JSON,但 { prop: “val” }和{ ‘prop’: ‘val’ } 不是有效的JSON。所有属性名和字符串值都必须用双引号包围,而不是单引号!对于PHP用户,请注意,转义单引号也是无效的。详细的语法规则可以到这里查看。

放到上下文里来看

大家可能会嗤之以鼻:难道JavaScript源代码不是只有一大串文本吗?

是的,当然是这样。所有的JavaScript和HTML(包括其他东西)都是文本字符串。直到它们被浏览器解释。这时.js文件或内联JavaScript代码在浏览器将其解释为JavaScript源代码,而不再是“一大串的文本字符串”,就像页面的innerHTML一样,在转换成DOM结构时不再是“一大串的文本字符串”。

再说一遍,这都是取决于上下文的。在字符串上下文中使用带括号的JavaScript对象,您就得到了一个JSON字符串。在对象字面量上下文中使用它,那它就是对象字面量。

JSON对象

开头已经提到,虽然对象文字不是“JSON对象”,但确实存在一个真正的JSON对象,但它完全是另一回事。在现代浏览器中,JSON对象是一个带有静态方法JSON.parse(将JSON字符串反序列化为对象)和JSON.stringify(将对象序列化为JSON字符串)的原生内置对象。当您想要转换为JSON时,您可以使用这些方法。老版本的浏览器不支持这个对象,但你可以通过json2.js来实现同样的功能。

如果你还不明白的话,别担心,这里有个小例子:

// 这是JSON字符串,比如从AJAX获取字符串信息
var my_json_string = '{ "prop": "val" }';

// 将字符串反序列化成对象
var my_obj = JSON.parse( my_json_string );

alert( my_obj.prop == 'val' ); // 提示 true, 和想象的一样!

// 将对象序列化成JSON字符串
var my_other_json_string = JSON.stringify( my_obj );

另外,Paul Irish提到Douglas Crockford在JSON RFC里用到了“JSON object”,但是在那个上下文里,他的意思是“以JSON字符串表示的对象”不是“对象字面量”。

更多资料

如果您想了解更多关于JSON的信息,这里有一些与JSON相关的链接,供您在闲暇时阅读。