RFC 8259最新的Json 規范
官方規范與其他規范
即使在最好的情況下,規范的實現也不可避免地存在一些輕微的、非故意的偏差。除此之外,JSON解析器還面臨一些額外的挑戰:即使在官方的JSON RFC中,也存在關於某些主題的開放式指導,例如如何處理重復的鍵和表示數字等。雖然這些指導后面有關於互操作性的免責聲明,但大多數JSON解析器的用戶並不了解這些注意事項。
造成解析器之間不一致的原因之一是存在多種不同的規范。
· IETF JSON RFC (8259及以前的版本):這是互聯網工程任務組(IETF)的官方規范。
· ECMAScript標准:對JSON的更改是與RFC版本同步發布的,該標准參考了RFC關於JSON的指導。然而,JavaScript解釋器提供的不合規范的便利性,如無引號字符串和注釋,則激發了許多解析器的“創造”靈感。
· JSON5:這個超集規范通過明確地添加便利性特征(如注釋、備選引號、無引號字符串、尾部逗號)來增強官方規范。
· HJSON:HJSON在思想上與JSON5類似,但在設計上則具有不同的選擇。
· 還有更多...
1.導言
——JavaScript對象表示法(JSON)是一種用於結構化數據序列化的文本格式。它來自JavaScript的對象文字,如ECMAScript編程語言標准第三版[ECMA-262]中定義的那樣。
——JSON可以表示四種基本類型(字符串、數字、布爾和NULL)和兩種結構化類型(對象Object和數組Array)。
————字符串是由零個或多個Unicode字符組成的序列[Unicode]。請注意,此引用引用的是Unicode的最新版本,而不是特定版本。預計未來對Unicode規范的更改不會影響JSON的語法。
————對象是零個或多個名稱/值對的無序集合,其中名稱是字符串,值是字符串、數字、布爾值、NULL、對象或數組。
————數組是一個零個或多個值的有序序列。
————術語“Object”和“Array”來自JavaScript的約定。JSON的設計目標是:它是最小的、可移植的、文本的和JavaScript的子集。
2.JSON語法
——JSON文本是一系列標記。這組標記包括六個結構字符、字符串、數字和三個文字名稱。
——JSON文本是一個序列化的值。注意,以前的某些JSON規范將JSON文本限制為對象或數組。只生成調用JSON文本的對象或數組的實現將是可互操作的,因為所有實現都將接受這些作為符合JSON文本的實現。
以下是六個結構字符:
在這六個結構字符中的任何一個之前或之后都允許使用不重要的空白字符ws。
3.值
——JSON值必須是數字、字符串、對象、數組,或以下三個文字名稱之一:
文字名稱必須是小寫。不允許使用其他文字名稱。
4.對象
——對象結構表示為圍繞零或多個名稱/值對(或多個成員)的一對花括號。名稱是字符串。在每個名稱之后加上一個冒號,將名稱與值分隔開來。一個逗號將值與接下來的名稱分隔開來。對象中的名稱應該是唯一的。
——所有名稱都唯一的對象是可互操作的,因為接收該對象的所有軟件實現都會在【名稱-值】映射上達成一致。當對象中的名稱不是唯一的時,接收此類對象的軟件的實現行為是不可預測的。許多實現只報告名稱/值對。其他實現會報告錯誤或無法解析對象,而一些實現則會報告所有名稱/值對,包括重復的名稱/值對。
——JSON解析庫對於它們是否使對象成員的排序對調用軟件是可見的,已經觀察到了不同的情況。其行為不依賴於成員排序的實現將是可互操作的,因為它們不會受到這些差異的影響。
5.數組
——數組結構表示為圍繞零個或多個值(或多個元素)的方括號。元素用逗號分隔。
——不要求數組中的值具有相同的類型。
6.數字
——數字的表示與大多數編程語言中使用的表示類似。一個數字用十進制數字以基數10表示。它包含一個整數分量,其前綴可以是可選減號,后面可以是分數部分和/或指數部分。不允許前導零。
——分數部分是小數點,后面跟着一個或多個數字。
——指數部分以大寫或小寫字母E開頭,后面可以是正負號。E和可選符號后面跟着一個或多個數字。
——不允許使用【不能用下面的語法表示的】數值(如Infinity和NaN)。
——該規范允許【implementations】對所接受的數字的范圍和精度設置限制。由於實現IEEE 754二進制64(雙精度)數字[IEEE 754]的軟件是普遍可用和廣泛使用的,因此只要【implementations】的精度或范圍不超過廣泛使用的標准,就可以實現良好的互操作性,因為【implementations】將在預期的精度范圍內近似於JSON數字。
——諸如1E400或3.14159265357932384626383279這樣的JSON數字可能有潛在的互操作性問題,因為如果創建的軟件使用這樣的數字,該創建的軟件會希望接收方軟件在數值范圍和精度方面比廣泛可用的軟件更大。
——請注意,當使用這種軟件時,屬於整數且在[-(253)+1,(253)-1]范圍內的數字是可互操作的,因為實現將精確地商定它們的數值。
7.字符串
——字符串的表示類似於C系列編程語言中使用的約定。字符串以單引號開頭和結尾。所有Unicode字符都可以放在引號中,但必須轉義的字符除外:引號、反斜線分隔符\和控制字符(U+0000到U+001 F)。
——任何字符都可以轉義。如果字符位於基本的多語言平面(從U+0000到U+FFFF),那么它可以表示為六個字符序列:反斜線分隔符\,后面跟着小寫字母u,后面跟着四個十六進制數字,編碼字符的代碼點。十六進制字母A到F可以是大寫字母,也可以是小寫字母。因此,例如,只包含一個反向Solidus字符的字符串可以表示為“\u005C”。
——另外,也有一些流行字符的雙字符序列轉義表示形式。因此,例如,只包含一個反向Solidus字符的字符串可以更緊湊地表示為“\”。
——為了轉義不屬於基本多語言平面的擴展字符,該字符被表示為12個字符序列,編碼UTF-16代理項對。因此,例如,只包含G clef字符(U+1D11E)的字符串可以表示為“\uD 834\uDD1E”。
8.字符串和字符問題
8.1.字符編碼
——在不屬於封閉生態系統的系統之間交換的JSON文本必須使用UTF-8[RFC 3629]編碼。
——以前的JSON規范在傳輸JSON文本時不需要使用UTF-8。然而,絕大多數基於JSON的軟件實現都選擇使用UTF-8編碼,因為它是實現互操作性的唯一編碼。
——【implementations】不能在網絡傳輸的JSON文本的開頭添加字節順序標記(U+FEFF)。為了實現互操作性,解析JSON文本的實現可能忽略字節順序標記的存在,而不是將其視為錯誤。
8.2.Unicode字符
——當在JSON文本中表示的所有字符串都由Unicode字符( 無論如何轉義 )組成時,那么JSON文本是可互操作的,因為解析它的所有軟件實現都將在對象和數組中的名稱和字符串值的內容上達成一致。
——但是,該規范中的ABNF允許成員名稱和字符串值包含不能編碼Unicode字符的位序列;例如“\uDEAD”(一個未配對的UTF-16代理項)。例如,當庫在不檢查截斷是否拆分代理項對的情況下截斷UTF-16字符串時,就會觀察到這種情況。接收包含這些值的JSON文本的軟件的行為是不可預測的;例如,實現可能返回字符串值長度的不同值,甚至會遇到致命的運行時異常。
8.3.字符串比較
——通常需要軟件實現來測試對象成員的名稱是否相等。將文本表示轉換為Unicode代碼單元的序列,然后按代碼單元進行數字比較的實現是可互操作的,因為在所有情況下,【implementations】都將同意兩個字符串的相等或不平等。例如,將字符串與未轉換的轉義字符進行比較的實現可能會錯誤地發現“a\ \b”和“a\u005Cb”不相等。
9.解析器
——JSON解析器將JSON文本轉換為另一種表示形式。JSON解析器必須接受符合JSON語法的所有文本。JSON解析器可以接受非JSON形式或擴展。
——【implementations】可以限制其接受的文本的大小,限制嵌套的最大深度,限制數字的范圍和精度,對字符串的長度和字符內容設置限制。
10.生成器
——JSON生成器生成JSON文本。得到的結果文本必須嚴格符合JSON語法。
12.安全考慮
——一般來說,腳本語言存在安全問題。JSON是JavaScript的一個子集,但不包括賦值和調用。
——由於JSON的語法是從JavaScript借用的,所以可以使用JavaScript的“eval()”函數來解析大多數JSON文本,但不是全部字符都能用它來解析。某些字符,例如U+2028行分隔符("\u2028")和U+2029段分隔符("\u2029")在JSON中是合法的,而在JavaScript中不合法。這通常構成不可接受的安全風險,因為文本可以包含可執行代碼和數據聲明。如果其他編程語言中同樣含有類似於eval()函數語法的函數,在使用這些類似的函數處理JSON文本時,同樣也要考慮這一點。
解決方法是:用\u2028和\u2029(轉義序列)替換每個U+2028和U+2029字符
13.實例
JSON對象:
該對象的成員Image是一個對象。而對象Image的成員Thumbnail(縮略圖)是一個對象,成員ID是一個數字數組。
JSON數組:
僅包含值的JSON文本: