添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

8.14. JSON 型別

JSON 資料型別用於儲存 RFC 7159 中所規範的 JSON(JavaScript Object Notation)資料。此類資料也可以儲存為 text,但是 JSON 資料型別的優點是可以根據 JSON 規則強制讓每個儲存的值必須是有效的值 。對於這些資料型別中儲存的資料,還提供了各種特定於 JSON 的函數和運算子。 另請參閱 第 9.16 節

PostgreSQL 提供了兩種儲存 JSON 資料的型別:json 和 jsonb。為了對這些資料型別實作有效的查詢機制,PostgreSQL 還提供了 8.14.6 節 中所描述的 jsonpath 資料型別。

json 和 jsonb 資料型別接受幾乎相同的內容集合作為輸入。實際主要的差別是效率。json 資料型別儲存與輸入字串完全相同的內容,處理函數必須在每次執行時重新解析;jsonb 資料型別則以分解後的二進位格式儲存,由於增加了轉換成本,因此資料輸入的速度稍慢,但由於後續不需要解析,因此處理速度明顯加快。jsonb 還支援索引處理,這是一個很大的優勢。

因為 json 型別儲存與輸入字串完全相同的內容,所以它將保留標記之間語義上無關的空白以及 JSON 物件中鍵的順序。另外,如果 JSON 內容物件包含相同的鍵不只一次,則所有鍵/值對都會保留。(處理函數會將最後一個值視為可用的值。)相比之下,jsonb 不會保留空白,不會保留物件中鍵的順序,也不會保留物件中重複的鍵。如果在輸入中指定了重複的鍵,則僅保留最後一個值。

通常,大多數應用程序應該將 JSON 資料儲存為 jsonb,除非有非常特殊的需求,例如關於物件中鍵的順序有一些傳統上的假設。

由於 PostgreSQL 每個資料庫只允許一種字元集的編碼。因此,除非資料庫編碼為 UTF8,否則 JSON 型別不可能嚴格符合 JSON 規範。嘗試直接使用資料庫編碼中無法表示的字元會失敗;相反,character 型別則允許使用可以在資料庫編碼中表示但不能以 UTF8 表示的字元。

RFC 7159 允許 JSON 字串包含 \uXXXX 所表示的 Unicode 轉譯序列。在 json 型別的輸入函數中,無論資料庫編碼如何,都允許 Unicode 轉譯,並且僅檢查語法正確性(即,四個十六進位數字跟在 \u 之後)。但是,jsonb 的輸入函數更嚴格:除非資料庫編碼為 UTF8,否則它不允許非 ASCII 字元(U+007F 以上的字元)使用 Unicode 轉譯。jsonb 型別也拒絕 \u0000(因為無法在 PostgreSQL 的 text 型別中表現),並且堅持認為使用 Unicode surrogate pair 對來指定 Unicode Basic Multilingual Plane 之外的字元都是正確的。有效的 Unicode 轉譯會轉換為等效的 ASCII 或 UTF8 字元進行儲存; 這包括將 surrogate pair 折疊為單個字元。

第 9.15 節中描述的許多 JSON 處理函數會將 Unicode 轉譯為一般字元,因此,即使輸入型別為 json 而不是 jsonb,它們也會拋出與上述類型相同的錯誤。json 輸入函數不進行這些檢查的事實可能被認為是歷史共業,儘管它確實允許以非 UTF8 資料庫編碼的形式簡單儲存(毋須處理)JSON Unicode 轉譯。 通常,如果可以的話,最好避免將 JSON 中的 Unicode 轉譯與非 UTF8 資料庫編碼混在一起。

將字串 JSON 輸入轉換為 jsonb 時,RFC 7159 描述的原始型別將會有效地對應到內建的 PostgreSQL 型別,如 Table 8.23 所示。因此,對於構成有效 jsonb 資料的內容存在一些較小的附加約束條件,這些約束條件既不適用於 json 型別,也不適用於抽象上 JSON,這對應於基礎資料型別可以表示的內容限制。值得注意的是,jsonb 會拒絕 PostgreSQL 數字資料型別範圍之外的數字,而 json 不會。RFC 7159 允許此類實作定義限制。但是,實際上,在其他實作中更容易出現此類問題,因為通常將 JSON 的數字基本型別表示為 IEEE 754 雙精確度浮點數(RFC 7159 明確預期了這一點且允許)。當使用 JSON 作為此類系統的交換格式時,應考慮與 PostgreSQL 最初儲存的資料相比較,可能會有失去數字精確度的風險。

相反,如下表中所示,JSON 基本型別的輸入格式有一些微小的限制,但並不適用於其相應的 PostgreSQL 資料型別。

Table 8.23. JSON Primitive Types and Corresponding PostgreSQL Types