支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2

8.14. JSON類型 #

JSON 資料類型用於儲存 JSON (JavaScript Object Notation) 資料,如 RFC 7159 中所指定。此類資料也可以儲存為 text,但 JSON 資料類型的優點是強制每個儲存的值都符合 JSON 規則。還有各種針對 JSON 的函式和運算符可用於儲存在這些資料類型中的資料;請參閱第 9.16 節

PostgreSQL 提供了兩種用於儲存 JSON 資料的類型:jsonjsonb。為了為這些資料類型實現有效的查詢機制,PostgreSQL 還提供了 jsonpath 資料類型,如第 8.14.7 節中所述。

jsonjsonb 資料類型接受幾乎完全相同的輸入值集合。主要的實際差異在於效率。json 資料類型儲存輸入文字的精確副本,處理函式每次執行都必須重新解析;而 jsonb 資料以分解的二進位格式儲存,由於增加了轉換開銷,因此輸入速度稍慢,但處理速度顯著加快,因為不需要重新解析。jsonb 也支援索引,這可能是一個顯著的優勢。

由於 json 類型儲存輸入文字的精確副本,因此它會保留 Token 之間語義上無關的空格,以及 JSON 物件中鍵的順序。此外,如果值中的 JSON 物件包含多個相同鍵,則會保留所有鍵/值對。(處理函式將最後一個值視為有效值。)相反,jsonb 不保留空格,不保留物件鍵的順序,也不保留重複的物件鍵。如果在輸入中指定了重複的鍵,則僅保留最後一個值。

一般來說,除非有非常特殊的需求,例如關於物件鍵排序的舊版假設,否則大多數應用程式應優先將 JSON 資料儲存為 jsonb

RFC7159 規定 JSON 字串應以 UTF8 編碼。因此,除非資料庫編碼是 UTF8,否則 JSON 類型不可能嚴格符合 JSON 規範。嘗試直接包含無法在資料庫編碼中表示的字元將會失敗;相反,允許使用可以在資料庫編碼中表示但在 UTF8 中無法表示的字元。

RFC7159 允許 JSON 字串包含 Unicode 跳脫序列,以 \uXXXX 表示。在 json 類型的輸入函式中,無論資料庫編碼如何,都允許使用 Unicode 跳脫序列,並且僅檢查語法正確性(也就是說,\u 後面跟著四個十六進位數字)。但是,jsonb 的輸入函式更嚴格:它不允許對無法在資料庫編碼中表示的字元使用 Unicode 跳脫序列。jsonb 類型還拒絕 \u0000(因為它無法在 PostgreSQLtext 類型中表示),並且它堅持必須正確使用 Unicode 代理配對來指定 Unicode 基本多文種平面之外的字元。有效的 Unicode 跳脫序列會轉換為用於儲存的等效單個字元;這包括將代理配對摺疊為單個字元。

注意

第 9.16 節中描述的許多 JSON 處理函式會將 Unicode 跳脫序列轉換為常規字元,因此即使它們的輸入類型是 json 而不是 jsonb,也會引發剛剛描述的相同類型的錯誤。事實上,json 輸入函式不進行這些檢查可能被認為是一個歷史產物,儘管它允許在不支援表示字元的資料庫編碼中簡單儲存(不處理)JSON Unicode 跳脫序列。

將文字 JSON 輸入轉換為 jsonb 時,由RFC7159 描述的基本類型會有效地對應到原生 PostgreSQL 類型,如表 8.23 中所示。因此,對於構成有效 jsonb 資料的內容有一些額外的限制,這些限制不適用於 json 類型,也不適用於抽象的 JSON,這些限制對應於底層資料類型可以表示的內容的限制。值得注意的是,jsonb 將拒絕超出 PostgreSQL numeric 資料類型範圍的數字,而 json 不會。此類實作定義的限制是RFC7159. 然而,在實務上,這類問題更有可能發生在其他實作中,因為通常會將 JSON 的 number 原始型別表示為 IEEE 754 雙精度浮點數(RFC7159 明確預期並允許這種情況)。當使用 JSON 作為與此類系統的交換格式時,應考慮到與 PostgreSQL 最初儲存的資料相比,可能會遺失數值精確度的風險。

反之,如表格中所述,JSON 原始型別的輸入格式存在一些微小的限制,這些限制不適用於對應的 PostgreSQL 型別。

表 8.23. JSON 原始型別與對應的 PostgreSQL 型別

JSON 原始型別 PostgreSQL 型別 注意事項
string (字串) text (文字) 不允許使用 \u0000,也不允許使用表示資料庫編碼中不可用字元的 Unicode 逸出序列
number (數字) numeric (數值) 不允許使用 NaNinfinity
boolean (布林值) boolean (布林值) 僅接受小寫的 truefalse 拼寫
null (空值) (none) (無) SQL NULL 是一個不同的概念

8.14.1. JSON 輸入與輸出語法 #

JSON 資料型別的輸入/輸出語法如文件中所述RFC 7159.

以下都是有效的 json(或 jsonb)表達式

-- Simple scalar/primitive value
-- Primitive values can be numbers, quoted strings, true, false, or null
SELECT '5'::json;

-- Array of zero or more elements (elements need not be of same type)
SELECT '[1, 2, "foo", null]'::json;

-- Object containing pairs of keys and values
-- Note that object keys must always be quoted strings
SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;

-- Arrays and objects can be nested arbitrarily
SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json;

如先前所述,當輸入一個 JSON 值然後在沒有任何額外處理的情況下印出時,json 會輸出與輸入相同的文字,而 jsonb 不會保留語義上不重要的細節,例如空白。例如,請注意此處的差異

SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
                      json
-------------------------------------------------
 {"bar": "baz", "balance": 7.77, "active":false}
(1 row)

SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
                      jsonb
--------------------------------------------------
 {"bar": "baz", "active": false, "balance": 7.77}
(1 row)

一個值得注意的語義上不重要的細節是,在 jsonb 中,數字將根據底層 numeric 型別的行為印出。實際上,這意味著使用 E 表示法輸入的數字將在印出時不帶有它,例如

SELECT '{"reading": 1.230e-5}'::json, '{"reading": 1.230e-5}'::jsonb;
         json          |          jsonb
-----------------------+-------------------------
 {"reading": 1.230e-5} | {"reading": 0.00001230}
(1 row)

但是,jsonb 將保留尾隨的小數點後的零,如本例所示,即使這些零對於相等性檢查等目的在語義上並不重要。

有關可用於建構和處理 JSON 值的內建函式和運算符清單,請參閱第 9.16 節

8.14.2. 設計 JSON 文件 #

將資料表示為 JSON 可以比傳統的關聯式資料模型更具彈性,這在需求不斷變化的環境中非常具有吸引力。這兩種方法完全有可能在同一個應用程式中共存並互補。但是,即使對於需要最大彈性的應用程式,仍然建議 JSON 文件具有某種程度上固定的結構。這種結構通常是不強制執行的(儘管可以宣告式地強制執行某些業務規則),但是具有可預測的結構可以更輕鬆地編寫查詢,以有效地總結表格中的一組 文件(資料)。

儲存在表格中時,JSON 資料與任何其他資料型別一樣,都受到相同的並行控制考量。雖然儲存大型文件是可行的,但請記住,任何更新都會在整個列上取得列層級鎖定。考慮限制 JSON 文件的大小,以便減少更新交易之間的鎖定爭用。理想情況下,每個 JSON 文件應代表一個原子資料,業務規則規定不能合理地將其進一步細分為可以獨立修改的較小資料。

8.14.3. jsonb 包含與存在 #

測試包含jsonb 的重要功能。 json 型別沒有平行的功能集合。包含測試檢查一個 jsonb 文件是否包含另一個文件。除非另有說明,否則以下範例傳回 true

-- Simple scalar/primitive values contain only the identical value:
SELECT '"foo"'::jsonb @> '"foo"'::jsonb;

-- The array on the right side is contained within the one on the left:
SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb;

-- Order of array elements is not significant, so this is also true:
SELECT '[1, 2, 3]'::jsonb @> '[3, 1]'::jsonb;

-- Duplicate array elements don't matter either:
SELECT '[1, 2, 3]'::jsonb @> '[1, 2, 2]'::jsonb;

-- The object with a single pair on the right side is contained
-- within the object on the left side:
SELECT '{"product": "PostgreSQL", "version": 9.4, "jsonb": true}'::jsonb @> '{"version": 9.4}'::jsonb;

-- The array on the right side is not considered contained within the
-- array on the left, even though a similar array is nested within it:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb;  -- yields false

-- But with a layer of nesting, it is contained:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb;

-- Similarly, containment is not reported here:
SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"bar": "baz"}'::jsonb;  -- yields false

-- A top-level key and an empty object is contained:
SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"foo": {}}'::jsonb;

一般原則是,被包含的物件必須在結構和資料內容上與包含物件匹配,可能在從包含物件中捨棄一些不匹配的陣列元素或物件鍵/值對之後。但是請記住,在執行包含匹配時,陣列元素的順序並不重要,並且重複的陣列元素實際上只被考慮一次。

作為結構必須匹配的一般原則的一個特殊例外,陣列可以包含一個原始值

-- This array contains the primitive string value:
SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb;

-- This exception is not reciprocal -- non-containment is reported here:
SELECT '"bar"'::jsonb @> '["bar"]'::jsonb;  -- yields false

jsonb 還有一個存在運算符,它是包含主題的一個變體:它測試一個字串(作為 text 值給出)是否作為 jsonb 值的頂層的物件鍵或陣列元素出現。除非另有說明,否則以下範例傳回 true

-- String exists as array element:
SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar';

-- String exists as object key:
SELECT '{"foo": "bar"}'::jsonb ? 'foo';

-- Object values are not considered:
SELECT '{"foo": "bar"}'::jsonb ? 'bar';  -- yields false

-- As with containment, existence must match at the top level:
SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- yields false

-- A string is considered to exist if it matches a primitive JSON string:
SELECT '"foo"'::jsonb ? 'foo';

當涉及許多鍵或元素時,JSON 物件比陣列更適合用於測試包含或存在,因為與陣列不同,它們在內部針對搜尋進行了優化,並且不需要線性搜尋。

提示

由於 JSON 包含是巢狀的,因此適當的查詢可以跳過子物件的顯式選擇。例如,假設我們有一個 doc 欄位,其中包含頂層的物件,並且大多數物件都包含 tags 欄位,其中包含子物件的陣列。此查詢查找包含 "term":"paris""term":"food" 的子物件的條目,同時忽略 tags 陣列之外的任何此類鍵

SELECT doc->'site_name' FROM websites
  WHERE doc @> '{"tags":[{"term":"paris"}, {"term":"food"}]}';

可以使用以下方法完成相同的事情,例如:

SELECT doc->'site_name' FROM websites
  WHERE doc->'tags' @> '[{"term":"paris"}, {"term":"food"}]';

但是,這種方法不太靈活,而且通常效率也較低。

另一方面,JSON 存在運算符不是巢狀的:它只會查找 JSON 值的頂層中指定的鍵或陣列元素。

各種包含和存在運算符,以及所有其他 JSON 運算符和函式,都記錄在第 9.16 節中。

8.14.4. jsonb 索引 #

GIN 索引可用於有效地搜尋大量 jsonb 文件(資料)中出現的鍵或鍵/值對。提供了兩個 GIN 運算符類別,提供不同的效能和靈活性權衡。

jsonb 的預設 GIN 運算符類別支援使用鍵存在運算符 ??|?&、包含運算符 @> 以及 jsonpath 匹配運算符 @?@@ 的查詢。(有關這些運算符實現的語義的詳細資訊,請參閱表 9.46。)使用此運算符類別建立索引的範例如下:

CREATE INDEX idxgin ON api USING GIN (jdoc);

非預設 GIN 運算符類別 jsonb_path_ops 不支援鍵存在運算符,但它支援 @>@?@@。使用此運算符類別建立索引的範例如下:

CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);

考慮一個表儲存從第三方 Web 服務檢索的 JSON 文件的範例,其中包含記錄的架構定義。一個典型的文件是

{
    "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
    "name": "Angela Barton",
    "is_active": true,
    "company": "Magnafone",
    "address": "178 Howard Place, Gulf, Washington, 702",
    "registered": "2009-11-07T08:53:22 +08:00",
    "latitude": 19.793713,
    "longitude": 86.513373,
    "tags": [
        "enim",
        "aliquip",
        "qui"
    ]
}

我們將這些文件儲存在名為 api 的表格中,在名為 jdocjsonb 欄位中。如果在該欄位上建立 GIN 索引,則以下查詢可以使用該索引

-- Find documents in which the key "company" has value "Magnafone"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';

但是,該索引不能用於以下查詢,因為雖然運算符 ? 是可索引的,但它不會直接應用於索引欄位 jdoc

-- Find documents in which the key "tags" contains key or array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';

不過,透過適當使用表達式索引,上述查詢可以使用索引。如果經常查詢 "tags" 鍵中的特定項目,那麼定義像這樣的索引可能是有價值的。

CREATE INDEX idxgintags ON api USING GIN ((jdoc -> 'tags'));

現在,WHERE 子句 jdoc -> 'tags' ? 'qui' 將被識別為對索引表達式 jdoc -> 'tags' 應用了可索引的運算符 ?。(有關表達式索引的更多資訊,請參閱第 11.7 節。)

另一種查詢方法是利用包含,例如:

-- Find documents in which the key "tags" contains array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';

jdoc 欄位上建立一個簡單的 GIN 索引可以支援此查詢。但請注意,這樣的索引將儲存 jdoc 欄位中每個鍵和值的副本,而前一個範例中的表達式索引僅儲存 tags 鍵下的資料。雖然簡單索引方法更具靈活性(因為它支援有關任何鍵的查詢),但目標表達式索引可能比簡單索引更小且搜尋速度更快。

GIN 索引也支援 @?@@ 運算符,它們執行 jsonpath 匹配。範例如下:

SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @? '$.tags[*] ? (@ == "qui")';
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] == "qui"';

對於這些運算符,GIN 索引從 jsonpath 模式中提取 accessors_chain == constant 形式的子句,並根據這些子句中提到的鍵和值進行索引搜尋。訪問器鏈可能包含 .key[*][index] 訪問器。jsonb_ops 運算符類別也支援 .*.** 訪問器,但 jsonb_path_ops 運算符類別則不支援。

儘管 jsonb_path_ops 運算符類別僅支援使用 @>@?@@ 運算符的查詢,但它比預設運算符類別 jsonb_ops 具有顯著的效能優勢。jsonb_path_ops 索引通常比相同資料上的 jsonb_ops 索引小得多,並且搜尋的精確度更高,尤其是在查詢包含資料中頻繁出現的鍵時。因此,搜尋操作的效能通常優於預設運算符類別。

jsonb_opsjsonb_path_ops GIN 索引之間的技術差異在於,前者為資料中的每個鍵和值建立獨立的索引項目,而後者僅為資料中的每個值建立索引項目。[7] 基本上,每個 jsonb_path_ops 索引項目都是值及其對應鍵的雜湊值;例如,要索引 {"foo": {"bar": "baz"}},將會建立一個單一索引項目,將 foobarbaz 全部包含在雜湊值中。因此,尋找此結構的包含查詢將產生非常精確的索引搜尋;但完全無法找出 foo 是否作為鍵出現。另一方面,jsonb_ops 索引將建立三個索引項目,分別代表 foobarbaz;然後,為了執行包含查詢,它會尋找包含所有這三個項目的列。雖然 GIN 索引可以相當有效率地執行這樣的 AND 搜尋,但它仍然不如等效的 jsonb_path_ops 搜尋那麼精確和快速,尤其是在有大量列包含這三個索引項目中的任何一個時。

jsonb_path_ops 方法的一個缺點是,它不會為不包含任何值的 JSON 結構(例如 {"a": {}})產生索引條目。如果請求搜尋包含此類結構的文件,則需要完整的索引掃描,這非常慢。jsonb_path_ops 因此不適合經常執行此類搜尋的應用程式。

jsonb 也支援 btreehash 索引。這些通常僅在檢查完整 JSON 文件的相等性非常重要時才有用。jsonb 資料的 btree 排序很少引起人們的興趣,但為了完整起見,它是:

Object > Array > Boolean > Number > String > Null

Object with n pairs > object with n - 1 pairs

Array with n elements > array with n - 1 elements

具有相同數量鍵值對的物件按以下順序比較:

key-1, value-1, key-2 ...

請注意,物件鍵按其儲存順序進行比較;特別是,由於較短的鍵儲存在較長的鍵之前,這可能會導致一些不直觀的結果,例如:

{ "aa": 1, "c": 1} > {"b": 1, "d": 1}

同樣,具有相同數量元素的陣列按以下順序比較:

element-1, element-2 ...

基本 JSON 值使用與底層 PostgreSQL 資料類型相同的比較規則進行比較。字串使用預設資料庫校對規則進行比較。

8.14.5. jsonb 下標 #

jsonb 資料類型支援陣列風格的下標表達式來提取和修改元素。巢狀值可以使用鏈式下標表達式來表示,遵循與 jsonb_set 函數中 path 參數相同的規則。如果 jsonb 值是一個陣列,則數字下標從零開始,負整數從陣列的最後一個元素向後計數。不支援切片表達式。下標表達式的結果始終為 jsonb 資料類型。

UPDATE 語句可以在 SET 子句中使用下標來修改 jsonb 值。對於所有受影響的值(如果存在),下標路徑必須是可以遍歷的。例如,如果每個 valval['a']val['a']['b'] 都是物件,則路徑 val['a']['b']['c'] 可以一直遍歷到 c。如果任何 val['a']val['a']['b'] 未定義,則將建立為空物件並根據需要進行填充。但是,如果任何 val 本身或其中間值定義為非物件(例如字串、數字或 jsonb null),則無法繼續遍歷,因此會引發錯誤並中止事務。

下標語法的範例:

-- Extract object value by key
SELECT ('{"a": 1}'::jsonb)['a'];

-- Extract nested object value by key path
SELECT ('{"a": {"b": {"c": 1}}}'::jsonb)['a']['b']['c'];

-- Extract array element by index
SELECT ('[1, "2", null]'::jsonb)[1];

-- Update object value by key. Note the quotes around '1': the assigned
-- value must be of the jsonb type as well
UPDATE table_name SET jsonb_field['key'] = '1';

-- This will raise an error if any record's jsonb_field['a']['b'] is something
-- other than an object. For example, the value {"a": 1} has a numeric value
-- of the key 'a'.
UPDATE table_name SET jsonb_field['a']['b']['c'] = '1';

-- Filter records using a WHERE clause with subscripting. Since the result of
-- subscripting is jsonb, the value we compare it against must also be jsonb.
-- The double quotes make "value" also a valid jsonb string.
SELECT * FROM table_name WHERE jsonb_field['key'] = '"value"';

透過下標的 jsonb 賦值處理一些與 jsonb_set 不同的邊緣情況。當來源 jsonb 值為 NULL 時,透過下標的賦值將像處理空 JSON 值一樣進行,該類型(物件或陣列)由下標鍵暗示。

-- Where jsonb_field was NULL, it is now {"a": 1}
UPDATE table_name SET jsonb_field['a'] = '1';

-- Where jsonb_field was NULL, it is now [1]
UPDATE table_name SET jsonb_field[0] = '1';

如果為包含過少元素的陣列指定了索引,則會附加 NULL 元素,直到可以到達該索引並設置該值為止。

-- Where jsonb_field was [], it is now [null, null, 2];
-- where jsonb_field was [0], it is now [0, null, 2]
UPDATE table_name SET jsonb_field[2] = '2';

jsonb 值將接受對不存在的下標路徑的賦值,只要要遍歷的最後一個現有元素是由相應下標暗示的物件或陣列即可(路徑中最後一個下標指示的元素不會被遍歷,並且可以是任何東西)。將會建立巢狀陣列和物件結構,並且在前一種情況下,會按照下標路徑的指定進行 null 填充,直到可以放置賦予的值為止。

-- Where jsonb_field was {}, it is now {"a": [{"b": 1}]}
UPDATE table_name SET jsonb_field['a'][0]['b'] = '1';

-- Where jsonb_field was [], it is now [null, {"a": 1}]
UPDATE table_name SET jsonb_field[1]['a'] = '1';

8.14.6. 轉換 #

其他擴充功能可用於實現不同程序語言的 jsonb 類型的轉換。

PL/Perl 的擴充套件稱為 jsonb_plperljsonb_plperlu。如果使用它們,jsonb 值會適當地對應到 Perl 陣列、雜湊和純量。

PL/Python 的擴充套件稱為 jsonb_plpython3u。如果使用它,jsonb 值會適當地對應到 Python 字典、列表和純量。

在這些擴充套件中,jsonb_plperl 被認為是 受信任的,也就是說,具有目前資料庫 CREATE 權限的非超級使用者也可以安裝。其餘的則需要超級使用者權限才能安裝。

8.14.7. jsonpath 類型 #

jsonpath 類型實作了 PostgreSQL 中的 SQL/JSON 路徑語言支援,以有效率地查詢 JSON 資料。它提供了已剖析的 SQL/JSON 路徑運算式的二進位表示法,該運算式指定路徑引擎要從 JSON 資料中檢索的項目,以便使用 SQL/JSON 查詢函式進一步處理。

SQL/JSON 路徑述詞和運算子的語意通常遵循 SQL。同時,為了提供使用 JSON 資料的自然方式,SQL/JSON 路徑語法使用了一些 JavaScript 慣例。

  • 點 (.) 用於成員存取。

  • 方括號 ([]) 用於陣列存取。

  • SQL/JSON 陣列是從 0 開始的,這與從 1 開始的正規 SQL 陣列不同。

SQL/JSON 路徑運算式中的數值常值遵循 JavaScript 規則,在某些細節上與 SQL 和 JSON 都有所不同。例如,SQL/JSON 路徑允許 .11.,這在 JSON 中是無效的。支援非十進制整數常值和底線分隔符,例如 1_000_0000x1EEE_FFFF0o2730b100101。在 SQL/JSON 路徑中(以及在 JavaScript 中,但在 SQL 本身中沒有),基數前綴後方不能直接有底線分隔符。

SQL/JSON 路徑運算式通常在 SQL 查詢中寫為 SQL 字元字串常值,因此必須用單引號括起來,並且值中所需的任何單引號都必須加倍(請參閱第 4.1.2.1 節)。某些形式的路徑運算式需要在其中包含字串常值。這些嵌入式字串常值遵循 JavaScript/ECMAScript 慣例:它們必須用雙引號括起來,並且可以在其中使用反斜線跳脫字元來表示其他難以輸入的字元。特別是,在嵌入式字串常值中寫入雙引號的方式是 \",而要寫入反斜線本身,則必須寫入 \\。其他特殊的反斜線序列包括 JavaScript 字串中識別的那些序列:\b\f\n\r\t\v 用於各種 ASCII 控制字元,\xNN 用於僅用兩個十六進制數字寫入的字元代碼,\uNNNN 用於由其 4 位十六進制數字代碼點標識的 Unicode 字元,以及 \u{N...} 用於用 1 到 6 個十六進制數字寫入的 Unicode 字元代碼點。

路徑運算式由一系列路徑元素組成,這些元素可以是下列任何一種:

  • JSON 基本類型的路徑常值:Unicode 文字、數值、true、false 或 null。

  • 表 8.24 中列出的路徑變數。

  • 表 8.25 中列出的存取器運算子。

  • 第 9.16.2.3 節中列出的 jsonpath 運算子和方法。

  • 括號,可用於提供篩選運算式或定義路徑評估的順序。

有關將 jsonpath 運算式與 SQL/JSON 查詢函式一起使用的詳細資訊,請參閱第 9.16.2 節

表 8.24. jsonpath 變數

變數 描述
$ 表示正在查詢的 JSON 值的變數(上下文項目)。
$varname 具名變數。其值可以由多個 JSON 處理函式的參數 vars 設置;有關詳細資訊,請參閱表 9.49
@ 表示篩選運算式中路徑評估結果的變數。

表 8.25. jsonpath 存取器

存取器運算子 描述

.key

."$varname"

成員存取器,傳回具有指定鍵值的物件成員。如果鍵名稱與以 $ 開頭的某些具名變數匹配,或不符合 JavaScript 識別符號的規則,則必須用雙引號括起來以使其成為字串常值。

.*

萬用字元成員存取器,傳回位於目前物件頂層的所有成員的值。

.**

遞迴萬用字元成員存取器,處理目前物件的 JSON 階層結構的所有層級,並傳回所有成員值,無論它們的巢狀層級如何。這是 SQL/JSON 標準的 PostgreSQL 擴充套件。

.**{level}

.**{start_level to end_level}

.** 類似,但僅選取 JSON 階層結構的指定層級。巢狀層級指定為整數。層級零對應於目前物件。若要存取最低巢狀層級,可以使用 last 關鍵字。這是 SQL/JSON 標準的 PostgreSQL 擴充套件。

[subscript, ...]

陣列元素存取器。subscript 可以採用兩種形式:indexstart_index to end_index。第一種形式會依索引傳回單一陣列元素。第二種形式會依索引範圍傳回陣列切片,包括與提供的 start_indexend_index 對應的元素。

指定的 index 可以是整數,也可以是傳回單一數值的運算式,該數值會自動轉換為整數。索引零對應於第一個陣列元素。您也可以使用 last 關鍵字來表示最後一個陣列元素,這對於處理未知長度的陣列非常有用。

[*]

萬用字元陣列元素存取器,傳回所有陣列元素。




[7] 為此,術語 包括陣列元素,儘管 JSON 術語有時會認為陣列元素與物件中的值不同。

提交更正

如果您在文件中看到任何不正確、與特定功能的經驗不符或需要進一步說明的內容,請使用此表單回報文件問題。