JSON
此條目需要補充更多來源。 (2017年5月11日) |
JSON(JavaScript Object Notation, /ˈdʒeɪsən/, JavaScript物件表示法)是由美國程式設計師道格拉斯·克羅克福特構想和設計的一種輕量級資料交換格式。其內容由屬性和值所組成,因此也有易於閱讀和處理的優勢。JSON是獨立於程式語言的資料格式,其不僅是JavaScript的子集,也採用了C語言家族的習慣用法,目前也有許多程式語言都能夠將其解析和字串化,其廣泛使用的程度也使其成為通用的資料格式。
副檔名 |
.json |
---|---|
網路媒體型式 |
application/json |
類型代碼 | TEXT |
統一類型標識 | public.json |
格式類型 | 數據交換 |
延伸自 | JavaScript |
標準 | RFC 7159, ECMA-404 |
網站 | json |
簡介
JSON格式是1999年《JavaScript Programming Language, Standard ECMA-262 3rd Edition》的子集合,所以可以在JavaScript以eval()
函數(javascript通過eval()呼叫解析器)讀入。不過這並不代表JSON無法使用於其他語言,事實上幾乎所有與網絡開發相關的語言都有JSON函數庫。
JSON的基本資料類型:
- 數值:十進制數,不能有前導0,可以為負數,可以有小數部分。還可以用
e
或者E
表示指數部分。不能包含非數,如NaN。不區分整數與浮點數。JavaScript用雙精度浮點數表示所有數值(後來也支援 BigInt[1])。 - 字串:以雙引號
""
括起來的零個或多個Unicode碼位。支援反斜槓開始的跳脫字元序列。 - 布林值:表示為
true
或者false
。 - 陣列:有序的零個或者多個值。每個值可以為任意類型。陣列使用方括號
[]
包裹。多個陣列元素之間用逗號,
分隔,形如:[value, value]
。 - 物件:若干無序的「鍵-值對」(key-value pairs),其中鍵只能是字串[2]。建議但不強制要求對象中的鍵是獨一無二的。對象以花括號
{}
包裹。多個鍵-值對之間使用逗號,
分隔。鍵與值之間用冒號:
分隔。 - 空值:值寫為
null
token(6種標點符號、字串、數值、3種字面量)之間可以存在有限的空白符並被忽略。四個特定字元被認為是空白符:空格符、水平制表符、回車字元、換行符。空白符不能出現在token內部(但空格符可以出現在字串內部)。JSON標準不允許有位元組序遮罩,不提供註釋的句法。 一個有效的JSON文件的根節點必須是一個對象或一個陣列。
JSON交換時必須編碼為UTF-8。[3]跳脫序列可以為:「\\」、「\"」、「\/」、「\b」、「\f」、「\n」、「\r」、「\t」,或Unicode16進制跳脫字元序列(\u後面跟隨4位元16進制數字)。對於不在基本多文種平面上的碼位,必須用UTF-16代理對(surrogate pair)表示,例如對於Emoji字元——喜極而泣的表情(U+1F602 😂 FACE WITH TEARS OF JOY)在JSON中應表示為:
{ "face": "😂" }
// or
{ "face": "\uD83D\uDE02" }
JSON的格式描述可以參考RFC 4627。
歷史
JSON 源於對即時伺服器到瀏覽器對談通訊協定的需求,無需使用 Flash 或 Java 小程式等瀏覽器外掛程式,這是 2000 年代初期使用的主要方法。
Crockford 首先指定並普及了 JSON 格式。這個縮寫詞起源於 State Software,這是一家由 Crockford 和其他人於 2001 年 3 月共同創立的公司。聯合創始人同意構建一個使用標準瀏覽器功能的系統,並為 Web 開發人員提供一個抽象層來建立有狀態的 Web 應用程式,該應用程式具有 通過保持兩個超文字傳輸協定 (HTTP) 連接打開並在標準瀏覽器逾時之前(如果沒有進一步交換數據)回收這些連接,實現與 Web 伺服器的持久雙工連接。 聯合創始人進行了討論,並投票決定將數據格式命名為 JSML(JavaScript 標記式語言)還是 JSON(JavaScript 物件表示法),以及在何種許可類型下提供該格式。 JSON.org 網站於 2001 年推出。
JSON 庫的前身被用於Cartoon Network的 Communities.com 上名為「Cartoon Orbit」的兒童數碼資產交易遊戲專案(State 聯合創始人之前都曾在這家公司工作過),該專案 使用具有專有訊息格式的瀏覽器端外掛程式來操作 DHTML 元素(該系統也屬於 3DO)。 在發現早期的 Ajax 功能後,digiGroups、Noosh 等公司使用框架將資訊傳遞到用戶瀏覽器的視野中,而無需重新整理 Web 應用程式的視覺上下文,僅使用標準 HTTP、HTML 和 JavaScript 功能即可實現即時豐富的 Web 應用程式 Netscape 4.0.5+ 和 IE 5+。 Crockford 隨後發現 JavaScript 可以用作此類系統的基於對象的訊息傳遞格式。 該系統被出售給 Sun Microsystems、Amazon.com 和 EDS。
應用領域
Metadata和架構
JSON文字的官方媒體類型是雙引號,這一點在大多數現代的安裝中都採用了這種類型。由於傳統原因,許多服務提供商、瀏覽器、伺服器、Web 應用程式、庫、框架和API也支援非官方的 MIME 類型 或內容類型。值得注意的例子包括谷歌搜尋API,雅虎,Facebook的API,Lift,和Dojo Toolkit。JSON 架構指定一種基於 JSON 的格式,用於定義用於驗證、文件和互動控制的 JSON 數據的結構。它為給定應用程式所需的 JSON 數據以及如何修改該數據提供協定。JSON架構基於XML架構(XSD)中的概念,但基於JSON。與在 XSD 中一樣,相同的序列化/反序列化工具可用於架構和數據,並且它是自描述的。它在IETF的互聯網草案中指定,目前為2020-12年草案,於2021年1月28日發佈。有幾個驗證器可用於不同的程式語言,每個驗證器都有不同程度的一致性。標準副檔名為 .json。JSON 標準不支援對象參照,但存在基於 JSON 的對象參照的 IETF 草案標準。
WEB開發
JSON最開始被廣泛的應用於WEB應用的開發。不過目前JSON使用在JavaScript、Java、Node.js、C#應用的情況比較多,PHP等開發的WEB應用主要還是使用XML。
NoSQL資料庫
相對於傳統的關係型資料庫,一些基於文件儲存的NoSQL非關係型資料庫選擇JSON作為其數據儲存格式,比較出名的產品有:MongoDB、CouchDB、RavenDB等。
舉例
{
"firstName": "John",
"lastName": "Smith",
"sex": "male",
"age": 25,
"address":
{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
},
"phoneNumber":
[
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
這種JSON格式也被不少遊戲(如Minecraft)或應用軟件用來當作的部分數據儲存的格式:
[
{
"text": "This is the text",
"color": "dark_red",
"bold": true,
"strikethough": true,
"clickEvent":
{
"action": "open_url",
"value": "zh.wikipedia.org"
},
"hoverEvent":
{
"action": "show_text",
"value":
{
"text": "something"
}
}
},
{
"translate": "item.dirt.name",
"color": "blue",
"bold": false,
"italic": true
}
]
互操作性
RFC 8259 (頁面存檔備份,存於互聯網檔案館)描述了 JSON 語法的某些方面,儘管這些方面符合規範,但可能會導致互操作性問題。
- 某些 JSON 實現僅接受表示對象或陣列的 JSON 文字。為了實現互操作性,交換 JSON 的應用程式應傳輸對象或陣列形式的訊息。
- 該規範允許 JSON 對象包含多個具有相同名稱的成員。處理具有重複名稱的對象的實現的行為是不可預測的。為了實現互操作性,應用程式在傳輸 JSON 對象時應避免重複名稱。
- 規範特別指出 JSON 對象中成員的順序並不重要。為了實現互操作性,應用程式應該避免為成員排序賦予含義,即使解析軟件使該排序可見。
- 雖然規範對 JSON 數字文字的大小或精度沒有限制,但廣泛使用的 JavaScript 實現將它們儲存為 IEEE754「binary64」數量。為了實現互操作性,應用程式應避免傳輸無法以這種方式表示的數字,例如 1E400 或 3.141592653589793238462643383279。
- 雖然規範不限制 JSON 文字中 Unicode 字元的字元編碼,但絕大多數實現都採用UTF-8編碼;為了實現互操作性,應用程式應始終且僅使用 UTF-8 對 JSON 訊息進行編碼。
- 該規範並不禁止傳輸不能正確表示 Unicode 字元的位元組序列。為了實現互操作性,應用程式應傳輸不包含此類位元組序列的訊息。
- 該規範不限制應用程式如何比較 Unicode 字串。為了實現互操作性,應用程式應始終逐個代碼單元執行此類比較。
2015 年,IETF 發佈了RFC7493 (頁面存檔備份,存於互聯網檔案館),描述了「I-JSON 訊息格式」,這是 JSON 的受限設定檔,它限制了 JSON 的語法和處理,以儘可能避免這些互操作性問題
安全問題
讀取JSON
由於JSON是JavaScript的子集,所以一般都會使用eval()
作為讀取資料的方式,如果是針對可靠的數據來源,在不支援原生JSON解析的瀏覽器上面這是最快速的方法。然而由於eval方法同樣可以執行任意的JavaScript代碼,因此當數據來源不可靠時則可能產生安全問題。如下面的例子,直接用eval執行時會跳轉:
var json= eval("{message:(function (){ window.location='http://zh.wikipedia.org/wiki/JSON#.E5.AE.89.E5.85.A8.E6.80.A7.E5.95.8F.E9.A1.8C'; })()}");
其中一種防止不安全程式碼出現的解決辦法,是通過瀏覽器原生支援的JSON.parse(str)
方法讀取JSON資料,目前已經得到大部分主流瀏覽器的支援(IE8+,Firefox 3.5+,Chrome4+/Safari4+,Opera10+),在不支援原生JSON對象的瀏覽器上面可以使用parseJSON
方法進行讀取[4],parseJSON
採用解析器驗證讀入的程式碼是否真的是JSON程式碼,這樣就更安全。但由於這是用模擬的方式讀取,速度上會比eval()
慢。
跨站存取問題
另外一個安全上的問題則是跨站請求偽造(Cross-site request forgery,簡稱CSRF或XSRF)。這個問題在JavaScript中的狀況是,由於JavaScript採用了稱為「沙盒」的機制,這種機制限制JavaScript引擎僅能引入同一個站點的程式碼,因而某種程度上提高了安全性。
與其他格式的比較
XML
JSON與XML最大的不同在於XML是一個完整的標記語言,而JSON不是。這使得XML在程式判讀上需要比較多的功夫。主要的原因在於XML的設計理念與JSON不同。XML利用標記語言的特性提供了絕佳的延展性(如XPath),在數據儲存,擴充及進階檢索方面具備對JSON的優勢,而JSON則由於比XML更加小巧,以及瀏覽器的內建快速解析支援,使得其更適用於網絡數據傳輸領域。
YAML
在功能和語法上,JSON 都是 YAML 語言的一個子集。特別是,YAML 1.2規範指定「任何JSON格式的檔案都是YAML格式的有效檔案"。最常見的YAML解析器也能夠處理JSON。版本 1.2 之前的 YAML 規範沒有完全涵蓋 JSON,主要是由於 YAML 中缺乏本機 UTF-32 支援,以及對逗號分隔空格的要求;此外,JSON 規範還包括 /* */ 樣式的註釋。YAML 最重要的區別是語法擴充集,它們在 JSON 中沒有類似物:關係數據支援:在 YAML 文件中,可以參照以前在檔案/流中找到的錨點;通過這種方式,您可以表達遞歸結構。支援除基元之外的可延伸資料類型,如字串、數字、布林值等。支援帶縮排的塊語法;它允許您在不使用不必要的符號的情況下描述結構化數據:各種括號、引號等。
MessagePack
MessagePack宣稱比JSON更短小,快速。
格式化工具
JSON格式取代了XML給網絡傳輸帶來了很大的便利,但是卻沒有了XML的一目了然,尤其是JSON數據很長的時候,會讓人陷入繁瑣複雜的數據節點尋找中。開發者可以使用線上JSON格式化工具,來更方便的對JSON數據進行節點尋找和解析。
參考文獻
- ^ BigInt - MDN Web Docs Glossary: Definitions of Web-related terms | MDN. developer.mozilla.org. 2023-06-08 [2023-06-12]. (原始內容存檔於2023-02-03) (美國英語).
- ^ MDN-JSON标准. [2021-10-30]. (原始內容存檔於2022-04-03).
- ^ The JavaScript Object Notation (JSON) Data Interchange Format. IETF. December 2017 [16 February 2018]. (原始內容存檔於2021-01-20).
- ^ JSON and Browser Security. [2007-07-14]. (原始內容存檔於2020-07-16).