本文澄清了JavaScript开发中常见的误区:将对象字面量误称为JSON对象。JSON本质上是一种数据交换格式的字符串,只有在字符串上下文中才称为JSON。文章通过对比展示了JSON字符串与对象字面量的语法差异,并介绍了ECMAScript 5新增的JSON对象及其parse和stringify方法,帮助开发者正确理解和使用数据序列化。
前言
前言
撰写本文旨在澄清一个高频出现的概念混淆:许多开发者常提及“将字符串转换为JSON对象”或“将JSON对象转换为字符串”。为此,我整理并翻译了一篇外文经典文章,供各位探讨指正。
正文
正文
本文基于ECMAScript 262-3标准展开讨论。虽然2011年发布的262-5新规范引入了JSON对象,这与日常所说的JSON相关,但二者并非同一概念。文章末尾将介绍这一新增的JSON对象。
英文原文:http://benalman.com/news/2010/03/theres-no-such-thing-as-a-json/
我想澄清一个普遍存在的误解:许多JavaScript开发者错误地将JavaScript对象字面量(Object Literals)称为JSON对象。尽管其语法与JSON规范描述的一致,但规范明确指出,JSON仅是一种数据交换语言,只有当它处于字符串上下文时,才能被称为JSON。
序列化与反序列化
序列化与反序列化
当两个程序(或服务器、语言等)需要交互通信时,它们倾向于使用字符串,因为字符串在多种语言中的解析方式大致相同。复杂的数据结构经常需要被传输,并通过各种大括号{}、小括号()、尖括号<>和空格组成。这个字符串仅仅是按照特定规范排列的字符。
为了描述这些复杂数据结构为字符串,我们制定了标准的规则和语法。JSON只是其中一种语法,它可以在字符串上下文中描述对象、数组、字符串、数字、布尔值和null,并通过程序间传输,随后反序列化为所需格式。YAML和XML(甚至request params)也是流行的数据交换格式,但作为JavaScript开发者,我们更偏爱JSON。
字面量
字面量
引用Mozilla Developer Center的几段话,供参考:
它们是固定的值,而非变量,让你从“字面上”理解脚本。(Literals)
字符串字面量由双引号(")或单引号(')包围的零个或多个字符组成。(Strings Literals)
对象字面量由大括号({})括起的零个或多个对象的属性名-值对组成。(Object Literals)
何时是JSON,何时不是JSON?
何时是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' }则不合法。所有属性名称及其值都必须用双引号包裹,严禁使用单引号。即使使用转义后的单引号也是不合法的,详细语法规则可查阅相关资料。
放到上下文里来看
放到上下文里来看
大家可能嗤之以鼻:难道JavaScript代码不是一个大的字符串?
确实如此,所有JavaScript代码和HTML(可能还有其他内容)在浏览器解析之前都是字符串。此时,.js文件或内联JavaScript代码已不再是字符串,而是被视为真正的JavaScript源代码,就像页面中的innerHTML一样,此时它也被解析为DOM结构,不再是字符串。
再次强调,这取决于上下文:在字符串上下文中使用带有大括号的JavaScript对象,它就是JSON字符串;而在对象字面量上下文中使用,它就是对象字面量。
真正的JSON对象
真正的JSON对象
开头已提及,对象字面量并非JSON对象,但确实存在真正的JSON对象。然而,两者概念完全不同。在新版浏览器中,JSON对象已成为原生内置对象,包含两个静态方法:JSON.parse用于将JSON字符串反序列化为对象,JSON.stringify用于将对象序列化为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 specification
- JSON RFC
- JSON on Wikipedia
- JSONLint - The JSON Validator
- JSON is not the same as JSON