深入理解JavaScript系列11:根本沒有“JSON物件”這回事

hiyangguo發表於2016-01-12

前言

寫這篇文章的目的是經常看到開發人員說:把字串轉化為JSON物件,把JSON物件轉化成字串等類似的話題,所以把之前收藏的一篇老外的文章整理翻譯了一下,供大家討論,如有錯誤,請大家指出,多謝。

正文

本文的主題是基於ECMAScript262-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 Objects),因為他的語法和JSON規範裡描述的一樣,但是該規範裡也明確地說了JSON只是一個資料交換語言,只有我們將之用在string上下文的時候它才叫JSON

定義

JSON(JavaScript Object Notation)是一種由道格拉斯·克羅克福特構想設計、輕量級的資料交換語言,以文字為基礎,且易於讓人閱讀。儘管JSON是Javascript的一個子集,但JSON是獨立於語言的文字格式,並且採用了類似於C語言家族的一些習慣。

詳細定義:https://zh.wikipedia.org/wiki/JSON

序列化與反序列化

兩個個程式(或伺服器、語言等)需要互動通訊的時候,他們傾向於使用string字串因為string在很多語言裡解析的方式都差不多。複雜的資料結構經常需要用到,並且通過各種各樣的中括號{},小括號(),叫括號<>和空格來組成,這個字串僅僅是按照要求規範好的字元。

為此,我們為了描述這些複雜的資料結構作為一個string字串,制定了標準的規則和語法。JSON只是其中一種語法,它可以在string上下文裡描述物件,陣列,字串,數字,布林型和null,然後通過程式間傳輸,並且反序列化成所需要的格式。YAMLXML(甚至request params)也是流行的資料交換格式,但是,我們喜歡JSON,誰叫我們是JavaScript開發人員呢!

字面量

引用Mozilla Developer Center裡的幾句話,供大家參考:

  1. 字面值:字面值是由語法表示式定義的常量;或,通過由一定字辭組成的語詞表示式定義的常量。 (Literals

  2. 字串字面值可以包含有零個或多個字元,由雙引號(”)對或單引號(‘)對包圍。字串被限定在同種引號之間;也即,必須是成對單引號或成對雙引號。(Strings Literals)

  3. 物件字面值是封閉在花括號對({})中的一個物件的零個或多個”屬性名-值”對的(元素)列表。(Object Literals)

何時是JSON,何時不是JSON?

JSON是設計成描述資料交換格式的,他也有自己的語法,這個語法是JavaScript的一個子集。
{ “prop”: “val” } 這樣的宣告有可能是JavaScript物件字面量也有可能是JSON字串,取決於在什麼上下文使用它,如果是用在string上下文(用單引號或雙引號引住,或者從text檔案讀取)的話,那它就是JSON字串,如果是用在物件字面量上下文中,那它就是物件字面量。

// 這是JSON字串
var foo = `{ "prop": "val" }`;

// 這是物件字面量
var bar = { "prop": "val" };

而且要注意,JSON有非常嚴格的語法,在string上下文裡{ "prop": "val" } 是個合法的JSON,但{ prop: "val" }{ `prop`: `val` }卻是不合法的。所有屬性名稱和它的值都必須用雙引號引住,不能使用單引號。另外,即便你用了轉義以後的單引號也是不合法的,詳細的語法規則可以到這裡檢視

放到上下文裡來看

大傢伙可能嗤之以鼻:難道JavaScript程式碼不是一個大的字串?

當然是,所有的JavaScript程式碼和HTML(可能還有其他東西)都是字串,直到瀏覽器對他們進行解析。這時候.js檔案或者inlineJavaScript程式碼已經不是字串了,而是被當成真正的JavaScript原始碼了,就像頁面裡的innterHTML一樣,這時候也不是字串了,而是被解析成DOM結構了。

再次說一下,這取決於上下文,在string上下文裡使用帶有大括號的JavaScript物件,那它就是JSON字串,而如果在物件字面量上下文裡使用的話,那它就是物件字面量。

真正的JSON物件

開頭已經提到,物件字面量不是JSON物件,但是有真正的JSON物件。但是兩者完全不一樣概念,在現代的瀏覽器裡JSON物件已經被原生的內建物件了,目前有2個靜態方法:JSON.parse()用來將JSON字串反序列化成物件,JSON.stringify()用來將物件序列化成JSON字串。老版本的瀏覽器(如ie6)不支援這個物件,但你可以通過json2.js或者json3.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的資料,下面的連線對你絕對有用:

關於本文

本文轉自TOM大叔深入理解JavaScript系列。宣告一下,本人所有整理的文章均不是照搬全抄,加入自己的理解和詳細的註解,以及修改了一些語病錯字等。

【深入理解JavaScript系列】文章,包括了原創,翻譯,轉載,整理等各型別文章,原文是TOM大叔的一個非常不錯的專題,現將其重新整理髮布。謝謝大叔。如果你覺得本文不錯,請幫忙點個推薦,支援一把,感激不盡。

更多優秀文章歡迎關注我的專欄

相關文章