

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# JSON 資料類型概觀
<a name="json-document-overview"></a>

ElastiCache 支援許多使用 JSON 資料類型的 Valkey 和 Redis OSS 命令。以下是 JSON 資料類型的概觀，以及支援命令的詳細清單。

## 術語
<a name="json-terminology"></a>


****  

| 術語 | 描述 | 
| --- | --- | 
|  JSON 文件 | 參考 JSON 金鑰的值。 | 
|  JSON 值 | 指一部分 JSON 文件，包括代表整份文件的根。值可以是容器或容器內的項目。 | 
|  JSON 元素 | 等於 JSON 值。 | 

## 支援的 JSON 標準
<a name="Supported-JSON-Standard"></a>

JSON 格式符合 [RFC 7159](https://www.ietf.org/rfc/rfc7159.txt) 和 [ECMA-404](https://www.ietf.org/rfc/rfc7159.txt) JSON 資料交換標準。支援 JSON 文字中的 UTF-8 [Unicode](https://www.unicode.org/standard/WhatIsUnicode.html)。

## 根元素
<a name="json-root-element"></a>

根元素可為任何 JSON 資料類型。請注意，在舊版 RFC 4627 中，只允許將物件或陣列當作根值。由於更新至 RFC 7159，JSON 文件的根可為任何 JSON 資料類型。

## 文件大小限制
<a name="json-document-size-limit"></a>

JSON 文件會以針對快速存取和修改最佳化的格式，儲存在內部。比起相同文件的等同序列化版本，這種格式一般會導致使用更多記憶體。

單一 JSON 文件的記憶體使用量限制為 64 MB，這是記憶體內資料結構的大小，而不是 JSON 字串。您可以使用 `JSON.DEBUG MEMORY` 命令，查看 JSON 文件使用的記憶體容量。

## JSON ACL
<a name="json-acls"></a>
+ 新類別 @json 類似於現有依資料類型類別 (@string、@hash 等)，加入以簡化管理 JSON 命令和資料的存取權。沒有其他現有的 Valkey 或 Redis OSS 命令是 @json 類別的成員。所有 JSON 命令都會強制執行任何索引鍵空間或命令限制和許可。
+ 有五個現有的 Valkey 和 Redis OSS ACL 類別已更新，以包含新的 JSON 命令：@read、@write、@fast、@slow 和 @admin。下表說明 JSON 命令對應至適當類別。


**ACL**  

| JSON 命令 | @read | @write | @fast | @slow | @admin | 
| --- | --- | --- | --- | --- | --- | 
|  JSON.ARRAPPEND |  | y | y |  |  | 
|  JSON.ARRINDEX | y |  | y |  |  | 
|  JSON.ARRINSERT |  | y | y |  |  | 
|  JSON.ARRLEN | y |  | y |  |  | 
|  JSON.ARRPOP |  | y | y |  |  | 
|  JSON.ARRTRIM |  | y | y |  |  | 
|  JSON.CLEAR |  | y | y |  |  | 
|  JSON.DEBUG | y |  |  | y | y | 
|  JSON.DEL |  | y | y |  |  | 
|  JSON.FORGET |  | y | y |  |  | 
|  JSON.GET | y |  | y |  |  | 
|  JSON.MGET | y |  | y |  |  | 
|  JSON.NUMINCRBY |  | y | y |  |  | 
|  JSON.NUMMULTBY |  | y | y |  |  | 
|  JSON.OBJKEYS | y |  | y |  |  | 
|  JSON.OBJLEN | y |  | y |  |  | 
|  JSON.RESP | y |  | y |  |  | 
|  JSON.SET |  | y |  | y |  | 
|  JSON.STRAPPEND |  | y | y |  |  | 
|  JSON.STRLEN | y |  | y |  |  | 
|  JSON.STRLEN | y |  | y |  |  | 
|  JSON.TOGGLE |  | y | y |  |  | 
|  JSON.TYPE | y |  | y |  |  | 
|  JSON.NUMINCRBY |  | y | y |  |  | 

## 巢狀深度限制
<a name="json-nesting-depth-limit"></a>

JSON 物件或陣列具有本身是另一個 JSON 物件或陣列的元素時，該內部物件或陣列稱之為在外部物件或陣列中「巢狀」。巢狀深度上限為 128。任何建立巢狀深度大於 128 文件的嘗試，都會遭到拒絕，並顯示錯誤。

## 命令語法
<a name="json-command-syntax"></a>

大多數命令需要金鑰名稱做為第一個引數。部分命令也有路徑引數。如果路徑引數為選用且未提供，則預設為根。

 標記法：
+ 必要引數以角括弧括住。例如：<key>
+ 選用引數以方括弧括住。例如：[path]
+ 其他選用引數會以省略號 ("…") 表示。例如：[json ...]

## 路徑語法
<a name="json-path-syntax"></a>

Redis JSON 支援兩種路徑語法：
+ **增強型語法** – 按照 [Goessner](https://goessner.net/articles/JsonPath/) 所述的 JSONPath 語法，如下表所示。為清楚說明，我們重新排序並修改表格中的描述。
+ **受限語法** – 查詢功能有限。

**注意**  
部分命令的結果對於使用哪種類型的路徑語法很敏感。

 如果查詢路徑以 '\$1' 開頭，它會使用增強型語法。否則，將使用受限語法。

**增強型語法**


****  

| 符號/表達式 | 描述 | 
| --- | --- | 
|  \$1 | 根元素。 | 
|  . 或 [] | 子運算子。 | 
|  .. | 遞迴下降。 | 
|  \$1 | 萬用字元。物件或陣列中的所有元素。 | 
|  [] | 陣列下標運算子。索引以 0 為基礎。 | 
|  [,] | 聯集運算子。 | 
|  [start:end:step] | 陣列分割運算子。 | 
|  ?() | 將篩選條件 (指令碼) 表達式套用至目前陣列或物件。 | 
|  () | 篩選條件表達式。 | 
|  @ | 用於指正在處理的目前節點的篩選條件表達式。 | 
|  == | 等於，用於篩選條件表達式。 | 
|  \$1= | 不等於，用於篩選條件表達式。 | 
|  > | 大於，用於篩選條件表達式。 | 
|  >= | 大於等於，用於篩選條件表達式。 | 
|  < | 小於，用於篩選條件表達式。 | 
|  <= | 小於等於，用於篩選條件表達式。 | 
|  && | 邏輯 AND，用於結合多個篩選條件表達式。 | 
|  \$1\$1 | 邏輯 OR，用於結合多個篩選條件表達式。 | 

**範例**

下列範例是根據 [Goessner](https://goessner.net/articles/JsonPath/) 的範例 XML 資料，我們已新增其他欄位來修改。

```
{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95,
        "in-stock": true,
        "sold": true
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99,
        "in-stock": false,
        "sold": true
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99,
        "in-stock": true,
        "sold": false
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99,
        "in-stock": false,
        "sold": false
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95,
      "in-stock": true,
      "sold": false
    }
  }
}
```


****  

| 路徑 | 描述 | 
| --- | --- | 
|  \$1.store.book[\$1].author | 商店中所有書籍的作者。 | 
|  \$1..author | 所有作者。 | 
|  \$1.store.\$1 | 商店的所有成員。 | 
|  \$1["store"].\$1 | 商店的所有成員。 | 
|  \$1.store..price | 商店裡所有商品的價格。 | 
|  \$1..\$1 | JSON 結構的所有遞迴成員。 | 
|  \$1..book[\$1] | 所有書籍。 | 
|  \$1..book[0] | 第一本書。 | 
|  \$1..book[-1] | 最後一本書。 | 
|  \$1..book[0:2] | 前兩本書。 | 
|  \$1..book[0,1] | 前兩本書。 | 
|  \$1..book[0:4] | 從索引 0 到 3 (不包括結尾索引) 的書籍。 | 
|  \$1..book[0:4:2] | 索引 0、2 的書籍。 | 
|  \$1..book[?(@.isbn)] | 有 ISBN 編號的所有書籍。 | 
|  \$1..book[?(@.price<10)] | 不到 10 美元的所有書籍。 | 
|  '\$1..book[?(@.price < 10)]' | 不到 10 美元的所有書籍。(如果路徑包含空格，必須以英文引號括住。) | 
|  '\$1..book[?(@["price"] < 10)]' | 不到 10 美元的所有書籍。 | 
|  '\$1..book[?(@.["price"] < 10)]' | 不到 10 美元的所有書籍。 | 
|  \$1..book[?(@.price>=10&&@.price<=100)] | 價格範圍介於 10 至 100 美元 (含) 的所有書籍。 | 
|  '\$1..book[?(@.price>=10 && @.price<=100)]' | 價格範圍介於 10 至 100 美元 (含) 的所有書籍。(如果路徑包含空格，必須以英文引號括住。) | 
|  \$1..book[?(@.sold==true\$1\$1@.in-stock==false)] | 售完或缺貨的所有書籍。 | 
|  '\$1..book[?(@.sold == true \$1\$1 @.in-stock == false)]' | 售完或缺貨的所有書籍。(如果路徑包含空格，必須以英文引號括住。) | 
|  '\$1.store.book[?(@.["category"] == "fiction")]' | 小說類別中的所有書籍。 | 
|  '\$1.store.book[?(@.["category"] \$1= "fiction")]' | 非小說類別中的所有書籍。 | 

其他篩選條件表達式範例：

```
127.0.0.1:6379> JSON.SET k1 . '{"books": [{"price":5,"sold":true,"in-stock":true,"title":"foo"}, {"price":15,"sold":false,"title":"abc"}]}'
OK
127.0.0.1:6379> JSON.GET k1 $.books[?(@.price>1&&@.price<20&&@.in-stock)]
"[{\"price\":5,\"sold\":true,\"in-stock\":true,\"title\":\"foo\"}]"
127.0.0.1:6379> JSON.GET k1 '$.books[?(@.price>1 && @.price<20 && @.in-stock)]'
"[{\"price\":5,\"sold\":true,\"in-stock\":true,\"title\":\"foo\"}]"
127.0.0.1:6379> JSON.GET k1 '$.books[?((@.price>1 && @.price<20) && (@.sold==false))]'
"[{\"price\":15,\"sold\":false,\"title\":\"abc\"}]"
127.0.0.1:6379> JSON.GET k1 '$.books[?(@.title == "abc")]'
[{"price":15,"sold":false,"title":"abc"}]

127.0.0.1:6379> JSON.SET k2 . '[1,2,3,4,5]'
127.0.0.1:6379> JSON.GET k2 $.*.[?(@>2)]
"[3,4,5]"
127.0.0.1:6379> JSON.GET k2 '$.*.[?(@ > 2)]'
"[3,4,5]"

127.0.0.1:6379> JSON.SET k3 . '[true,false,true,false,null,1,2,3,4]'
OK
127.0.0.1:6379> JSON.GET k3 $.*.[?(@==true)]
"[true,true]"
127.0.0.1:6379> JSON.GET k3 '$.*.[?(@ == true)]'
"[true,true]"
127.0.0.1:6379> JSON.GET k3 $.*.[?(@>1)]
"[2,3,4]"
127.0.0.1:6379> JSON.GET k3 '$.*.[?(@ > 1)]'
"[2,3,4]"
```

**受限語法**


****  

| 符號/表達式 | 描述 | 
| --- | --- | 
|  . 或 [] | 子運算子。 | 
|  [] | 陣列下標運算子。索引以 0 為基礎。 | 

**範例**


****  

| 路徑 | 描述 | 
| --- | --- | 
|  .store.book[0].author | 第一本書的作者。 | 
|  .store.book[-1].author | 最後一本書的作者。 | 
|  .address.city | 城市名稱。 | 
|  ["store"]["book"][0]["title"] | 第一本書的標題。 | 
|  ["store"]["book"][-1]["title"] | 最後一本書的標題。 | 

**注意**  
本文件中引用的所有 [Goessner](https://goessner.net/articles/JsonPath/) 內容均受[創用 CC 授權](https://creativecommons.org/licenses/by/2.5/)規範。

## 常見錯誤字首
<a name="json-error-prefixes"></a>

每個錯誤訊息都有一個字首。以下是常見錯誤字首清單。


****  

| 字首 | 描述 | 
| --- | --- | 
|  ERR | 一般錯誤。 | 
|  LIMIT | 超過大小上限時發生的錯誤。例如，超過文件大小上限或巢狀深度限制。 | 
|  NONEXISTENT | 沒有索引鍵或路徑。 | 
|  OUTOFBOUNDARIES | 超出範圍的陣列索引。 | 
|  SYNTAXERR | 語法錯誤。 | 
|  WRONGTYPE | 錯誤值類型。 | 

## JSON 相關指標
<a name="json-info-metrics"></a>

提供下列 JSON 資訊指標：


****  

| Info | 描述 | 
| --- | --- | 
|  json\$1total\$1memory\$1bytes | 分配給 JSON 物件的總記憶體。 | 
|  json\$1num\$1documents | Valkey 或 Redis OSS 中的文件總數。 | 

若要查詢核心指標，請執行下列命令：

```
info json_core_metrics
```

## ElastiCache for Valkey 和 Redis OSS 如何與 JSON 互動
<a name="json-differences"></a>

下一節說明 ElastiCache for Valkey 和 Redis OSS 如何與 JSON 資料類型互動。

### 運算子優先順序
<a name="json-operator-precedence"></a>

評估用於篩選的條件表達式時，&& 優先，然後評估 \$1\$1，就像大多數語言一樣。系統會先執行括弧內的操作。

### 路徑巢狀上限行為
<a name="json-max-path"></a>

 ElastiCache for Redis OSS 中的最大路徑巢狀限制為 128。`$.a.b.c.d...` 等值只能達到 128 個等級。

### 處理數值
<a name="json-about-numbers"></a>

JSON 沒有另外的整數和浮點數資料類型。均稱為數字。

數值表示法：

輸入收到 JSON 數字時，數字會轉換為兩個內部二進位表示法之一：64 位元帶正負號的整數，或 64 位元 IEEE 雙精確度浮點數。不會保留原始字串和全部格式化。因此，數字當作 JSON 回應的一部分輸出時，會從內部二進位表示法，轉換為使用一般格式化規則的可列印字串。這些規則可能導致產生的字串與接收的字串不同。

算術命令 `NUMINCRBY` 和 `NUMMULTBY`：
+ 如果兩個數字都是整數，且結果超出 `int64` 範圍，會自動變成 64 位元 IEEE 雙精確度浮點數。
+ 如果其中至少一個數字是浮點數，結果會是 64 位元 IEEE 雙精確度浮點數。
+ 如果結果超過 64 位元 IEEE 雙精確度範圍，命令會傳回 `OVERFLOW` 錯誤。

如需可用命令的詳細清單，請參閱[支援的 Valkey 和 Redis OSS 命令JSON 命令](json-list-commands.md)。

### 直接陣列篩選
<a name="json-direct-array-filtering"></a>

ElastiCache for Valkey 或 Redis OSS 會直接篩選陣列物件。

對於 之類的資料`[0,1,2,3,4,5,6]`和 之類的路徑查詢`$[?(@<4)]`，或 之類的資料`{"my_key":[0,1,2,3,4,5,6]}`和 之類的路徑查詢`$.my_key[?(@<4)]`，ElastiCache 會在這兩種情況下傳回 【1，2，3】。

### 陣列索引行為
<a name="json-direct-array-indexing"></a>

ElastiCache for Valkey 或 Redis OSS 允許陣列的正索引和負索引。針對長度為五的陣列，0 會查詢第一個元素，1 會查詢第二個，以此類推。負數從陣列結尾開始，所以 -1 會查詢第五個元素，-2 會查詢第四個元素，以此類推。

為了確保客戶的可預測行為，ElastiCache 不會將陣列索引向下或向上四捨五入，因此如果您的陣列長度為 5，呼叫索引 5 或更高，或 -6 或更低，則不會產生結果。

### 嚴格語法評估
<a name="json-strict-syntax-evaluation"></a>

即使路徑的子集包含有效路徑，MemoryDB 也不允許使用無效語法的 JSON 路徑。這是為了我們的客戶保持正確行為。