

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 开始使用 JSON
<a name="json-gs"></a>

MemoryDB 支持原生 JavaScript 对象表示法 (JSON) 格式，这是一种在 Valkey 或 Redis OSS 集群中对复杂数据集进行编码的简单、无架构的方式。您可以在集群内使用 JavaScript 对象表示法 (JSON) 格式在本地存储和访问数据，并更新存储在这些集群中的 JSON 数据，而无需管理自定义代码来对其进行序列化和反序列化。

除了将 Valkey 或 Redis OSS APIs 用于通过 JSON 运行的应用程序外，您现在还可以高效地检索和更新 JSON 文档的特定部分，而无需操作整个对象，这可以提高性能并降低成本。您还可以使用 [Goessner 样式的](https://goessner.net/articles/JsonPath/) `JSONPath` 查询来搜索您的 JSON 文档内容。

使用受支持的引擎版本创建集群后，JSON 数据类型和关联的命令将自动可用。这与版本 2 的 RedisJSON 模块的 API 和 RDB 都兼容，因此您可以轻松地将现有的基于 JSON 的 Valkey 或 Redis OSS 应用程序迁移到 MemoryDB。有关受支持的命令的更多信息，请参阅 [支持的 命令](json-list-commands.md)。

与 JSON 相关的指标`JsonBasedCmds`已纳入其中 CloudWatch ，以监控此数据类型的使用情况。有关更多信息，请参阅 [MemoryDB 的指标](https://docs.aws.amazon.com/memorydb/latest/devguide/metrics.memorydb.html)。

**注意**  
要使用 JSON，您必须运行 Valkey 7.2 或更高版本，或运行 Redis OSS 引擎版本 6.2.6 或更高版本。

**Topics**
+ [JSON 数据类型概述](json-document-overview.md)
+ [支持的 命令](json-list-commands.md)

# JSON 数据类型概述
<a name="json-document-overview"></a>

MemoryDB 支持许多用于处理 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 ACLs
<a name="json-acls"></a>
+ JSON 数据类型完全集成到 Valkey 和 Redis OSS [访问控制列表（ACL）](https://valkey.io/topics/acl/)功能中。与现有的每数据类型类别（@string、@hash 等）类似，添加了一个新的类别 @json，以简化对 JSON 命令和数据的访问管理。没有其他现有的 Valkey 或 Redis OSS 命令属于 @json 类别。所有 JSON 命令均强制执行任何键空间或命令限制和权限。
+ 有五个现有的 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>

大多数命令均要求将 Valkey 或 Redis OSS 键名称作为第一个参数。某些命令还带有一个路径参数。如果该路径参数是可选的且未提供，则默认为根目录。

 表示法：
+ 必需的参数括在尖括号内，例如：<key>
+ 可选的参数括在方括号内，例如 [path]
+ 其他可选参数由…表示，例如 [json…]

## 路径语法
<a name="json-path-syntax"></a>

Valkey 和 Redis OSS 的 JSON 支持两种路径语法：
+ **增强语法**-遵循 [Goessner](https://goessner.net/articles/JsonPath/) 描述的 JSONPath 语法，如下表所示。我们对表中的描述进行了重新排序和修改使其更加清楚。
+ **受限的语法** – 查询功能有限。

**注意**  
某些命令的结果对使用哪种类型的路径语法很敏感。

 如果查询路径以“\$1”开头，则使用的是增强的语法。否则使用的是受限的语法。

**增强的语法**


****  

| 符号/表达式 | 说明 | 
| --- | --- | 
|  \$1 | 根元素 | 
|  . 或 [] | 子运算符 | 
|  .. | 递归下降 | 
|  \$1 | 通配符。对象或数组中的所有元素。 | 
|  [] | 数组下标运算符。索引从 0 开始。 | 
|  [,] | 联合运算符 | 
|  [start:end:step] | 数组 Slice 运算符 | 
|  ?() | 将筛选（脚本）表达式应用于当前的数组或对象 | 
|  () | 筛选表达式 | 
|  @ | 用于引用当前正在处理的节点的筛选表达式 | 
|  == | 等于，用于筛选表达式。 | 
|  \$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 美元之间（含 10 美元和 100 美元）的书籍 | 
|  '\$1..book[?(@.price>=10 && @.price<=100)]' | 所有价格在 10 美元到 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/) 内容均受[知识共享许可证](https://creativecommons.org/licenses/by/2.5/)的约束。

## 常见错误前缀
<a name="json-error-prefixes"></a>

每条错误消息均有一个前缀。以下是常见错误前缀的列表：


****  

| Prefix | 说明 | 
| --- | --- | 
|  ERR | 一般性错误 | 
|  LIMIT | 超出大小限制错误。例如，超出文档大小限制或嵌套深度限制 | 
|  NONEXISTENT | 键或路径不存在 | 
|  OUTOFBOUNDARIES | 数组索引超出界限 | 
|  SYNTAXERR | 语法错误 | 
|  WRONGTYPE | 错误的值类型 | 

## JSON 相关指标
<a name="json-info-metrics"></a>

提供了以下 JSON 信息指标：


****  

| 信息 | 说明 | 
| --- | --- | 
|  json\$1total\$1memory\$1bytes | 分配给 JSON 对象的总内存 | 
|  json\$1num\$1documents | Valkey 或 Redis OSS 引擎中的文档总数 | 

要查询核心指标，请运行命令：

```
info json_core_metrics
```

## MemoryDB 如何与 JSON 交互
<a name="json-differences"></a>

以下内容说明了 MemoryDB 如何与 JSON 数据类型交互。

### 运算符优先顺序
<a name="json-operator-precedence"></a>

当评估条件表达式以进行筛选时，&& 优先评估，然后评估 \$1\$1，这一点在大多数语言中很常见。首先执行括号内的操作。

### 最大路径嵌套限制行为
<a name="json-max-path"></a>

MemoryDB 的最大路径嵌套限制为 128。因此，像 `$.a.b.c.d...` 这样的值只能达到 128 个级别。

### 处理数字值
<a name="json-about-numbers"></a>

JSON 没有针对整数和浮点数的单独数据类型。它们都被称为数字。

当接收 JSON 数字时，以两种格式之一存储该数字。如果该数字适合 64 位有符号整数，则将其转换为该格式；否则，将其存储为字符串。尽量保持两个 JSON 数字（例如 JSON.NUMINCRBY 和 JSON.NUMMULTBY）的算术运算精度。如果两个操作数和结果值适合一个 64 位有符号整数，则执行整数运算。否则，输入操作数将转换为 64 位 IEEE 双精度浮点数，执行算术运算，并将结果转换回字符串。

算术命令 `NUMINCRBY` 和 `NUMMULTBY`：
+ 如果两个数字都是整数并且结果超出 int64 的范围，则它会自动变成一个双精度浮点数。
+ 如果至少有一个数字是浮点，则结果将是双精度浮点数。
+ 如果结果超出双精度值的范围，则该命令将返回 `OVERFLOW` 错误。

**注意**  
在 Redis OSS 引擎版本 6.2.6.R2 之前，如果在输入时接收 JSON 数字，它会转换为两种内部二进制表示之一：64 位有符号整数或 64 位 IEEE 双精度浮点。不保留原始字符串及其所有格式。因此，当数字作为 JSON 响应的一部分输出时，它会从内部二进制表示转换为使用通用格式规则的可打印字符串。这些规则可能会导致生成的字符串与收到的字符串不同。  
如果两个数字都是整数并且结果超出 `int64` 的范围，则它会自动变成一个 64 位 IEEE 双精度浮点数。
如果至少有一个数字是浮点，则结果是 64 位 IEEE 双精度浮点数。
如果结果超出 64 位 IEEE 双精度值的范围，则该命令将返回 `OVERFLOW` 错误。

有关可用命令的详细列表，请参阅 [支持的 命令](json-list-commands.md)。

### 严格语法评估
<a name="json-strict-syntax-evaluation"></a>

MemoryDB 不允许使用无效语法的 JSON 路径，即使路径的子集包含有效路径也是如此。这是为了维护我们客户的正确行为。

# 支持的 命令
<a name="json-list-commands"></a>

支持以下 JSON 命令：

**Topics**
+ [JSON.ARRAPPEND](json-arrappend.md)
+ [JSON.ARRINDEX](json-arrindex.md)
+ [JSON.ARRINSERT](json-arrinsert.md)
+ [JSON.ARRLEN](json-arrlen.md)
+ [JSON.ARRPOP](json-arrpop.md)
+ [JSON.ARRTRIM](json-arrtrim.md)
+ [JSON.CLEAR](json-clear.md)
+ [JSON.DEBUG](json-debug.md)
+ [JSON.DEL](json-del.md)
+ [JSON.FORGET](json-forget.md)
+ [JSON.GET](json-get.md)
+ [JSON.MGET](json-mget.md)
+ [JSON.NUMINCRBY](json-numincrby.md)
+ [JSON.NUMMULTBY](json-nummultby.md)
+ [JSON.OBJLEN](json-objlen.md)
+ [JSON.OBJKEYS](json-objkeys.md)
+ [JSON.RESP](json-resp.md)
+ [JSON.SET](json-set.md)
+ [JSON.STRAPPEND](json-strappend.md)
+ [JSON.STRLEN](json-strlen.md)
+ [JSON.TOGGLE](json-toggle.md)
+ [JSON.TYPE](json-type.md)

# JSON.ARRAPPEND
<a name="json-arrappend"></a>

将一个或多个值附加到路径上的数组值。

语法

```
JSON.ARRAPPEND <key> <path> <json> [json ...]
```
+ key（必需）– JSON 文档类型的键
+ path（必需）– 一个 JSON 路径
+ json（必需）– 要附加到数组的 JSON 值

**Return**

如果路径是增强的语法：
+ 表示每个路径处数组的新长度的整数数组。
+ 如果值不是数组，则其对应的返回值为 Null。
+ 如果输入 json 参数之一不是有效的 JSON 字符串，则为 `SYNTAXERR` 错误。
+ 如果路径不存在，则为 `NONEXISTENT` 错误。

如果路径是受限的语法：
+ 整数，该数组的新长度。
+ 如果选择了多个数组值，该命令将返回上次更新数组的新长度。
+ 如果路径中的值不是数组，则为 `WRONGTYPE` 错误。
+ 如果输入 json 参数之一不是有效的 JSON 字符串，则为 `SYNTAXERR` 错误。
+ 如果路径不存在，则为 `NONEXISTENT` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRAPPEND  k1 $[*] '"c"'
1) (integer) 1
2) (integer) 2
3) (integer) 3
127.0.0.1:6379> JSON.GET k1
"[[\"c\"],[\"a\",\"c\"],[\"a\",\"b\",\"c\"]]"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRAPPEND  k1 [-1] '"c"'
(integer) 3
127.0.0.1:6379> JSON.GET k1
"[[],[\"a\"],[\"a\",\"b\",\"c\"]]"
```

# JSON.ARRINDEX
<a name="json-arrindex"></a>

搜索标量 JSON 值在路径的数组中的首次出现。
+ 超出范围错误的处理方法是将索引舍入到数组的开头和结尾。
+ 如果 start > end，则返回 -1（未找到）。

语法

```
JSON.ARRINDEX <key> <path> <json-scalar> [start [end]]
```
+ key（必需）– JSON 文档类型的键
+ path（必需）– 一个 JSON 路径
+ json-scalar（必需）– 要搜索的标量值；JSON 标量是指不是对象或数组的值。即字符串、数字、布尔值和 null 都是标量值。
+ start（可选）– 起始索引（含）。如果未提供，则默认为 0。
+ end（可选）– 结束索引（不含）。如果未提供，则默认为 0，这意味着包含最后一个元素。0 或 -1 意味着包含最后一个元素。

**Return**

如果路径是增强的语法：
+ 整数数组。每个值都是路径内数组中匹配元素的索引。如果未找到，则值为 -1。
+ 如果值不是数组，则其对应的返回值为 Null。

如果路径是受限的语法：
+ 整数、匹配元素的索引，如果未找到，则为 -1。
+ 如果路径中的值不是数组，则为 `WRONGTYPE` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRINDEX k1 $[*] '"b"'
1) (integer) -1
2) (integer) -1
3) (integer) 1
4) (integer) 1
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"children": ["John", "Jack", "Tom", "Bob", "Mike"]}'
OK
127.0.0.1:6379> JSON.ARRINDEX k1 .children '"Tom"'
(integer) 2
```

# JSON.ARRINSERT
<a name="json-arrinsert"></a>

将一个或多个值插入到索引之前路径处的数组值中。

语法

```
JSON.ARRINSERT <key> <path> <index> <json> [json ...]
```
+ key（必需）– JSON 文档类型的键
+ path（必需）– 一个 JSON 路径
+ index（必需）– 在其前面插入值的数组索引。
+ json（必需）– 要附加到数组的 JSON 值

**Return**

如果路径是增强的语法：
+ 表示每个路径处数组的新长度的整数数组。
+ 如果值为空数组，则其对应的返回值为 Null。
+ 如果值不是数组，则其对应的返回值为 Null。
+ 如果索引参数超出界限，则为 `OUTOFBOUNDARIES` 错误。

如果路径是受限的语法：
+ 整数，该数组的新长度。
+ 如果路径中的值不是数组，则为 `WRONGTYPE` 错误。
+ 如果索引参数超出界限，则为 `OUTOFBOUNDARIES` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRINSERT k1 $[*] 0 '"c"'
1) (integer) 1
2) (integer) 2
3) (integer) 3
127.0.0.1:6379> JSON.GET k1
"[[\"c\"],[\"c\",\"a\"],[\"c\",\"a\",\"b\"]]"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRINSERT k1 . 0 '"c"'
(integer) 4
127.0.0.1:6379> JSON.GET k1
"[\"c\",[],[\"a\"],[\"a\",\"b\"]]"
```

# JSON.ARRLEN
<a name="json-arrlen"></a>

获取路径中数组值的长度。

语法

```
JSON.ARRLEN <key> [path] 
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 表示每个路径处数组长度的整数数组。
+ 如果值不是数组，则其对应的返回值为 Null。
+ 如果文档键不存在，则为 Null。

如果路径是受限的语法：
+ 批量字符串数组。每个元素都是对象中的键名称。
+ 整数，数组长度。
+ 如果选择了多个对象，该命令将返回第一个数组的长度。
+ 如果路径中的值不是数组，则为 `WRONGTYPE` 错误。
+ 如果路径不存在，则为 `WRONGTYPE` 错误。
+ 如果文档键不存在，则为 Null。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], [\"a\"], [\"a\", \"b\"], [\"a\", \"b\", \"c\"]]'
(error) SYNTAXERR Failed to parse JSON string due to syntax error
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRLEN k1 $[*]
1) (integer) 0
2) (integer) 1
3) (integer) 2
4) (integer) 3

127.0.0.1:6379> JSON.SET k2 . '[[], "a", ["a", "b"], ["a", "b", "c"], 4]'
OK
127.0.0.1:6379> JSON.ARRLEN k2 $[*]
1) (integer) 0
2) (nil)
3) (integer) 2
4) (integer) 3
5) (nil)
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRLEN k1 [*]
(integer) 0
127.0.0.1:6379> JSON.ARRLEN k1 $[3]
1) (integer) 3

127.0.0.1:6379> JSON.SET k2 . '[[], "a", ["a", "b"], ["a", "b", "c"], 4]'
OK
127.0.0.1:6379> JSON.ARRLEN k2 [*]
(integer) 0
127.0.0.1:6379> JSON.ARRLEN k2 $[1]
1) (nil)
127.0.0.1:6379> JSON.ARRLEN k2 $[2]
1) (integer) 2
```

# JSON.ARRPOP
<a name="json-arrpop"></a>

从数组中删除并返回索引处的元素。弹出空数组会返回 Null。

语法

```
JSON.ARRPOP <key> [path [index]]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录
+ index（可选）– 数组中要开始弹出的位置。
  + 如果未提供，则默认为 -1，这表示最后一个元素。
  + 负值表示距离最后一个元素的位置。
  + 超出边界的索引会舍入到其各自的数组边界。

**Return**

如果路径是增强的语法：
+ 表示每个路径上弹出值的批量字符串数组。
+ 如果值为空数组，则其对应的返回值为 Null。
+ 如果值不是数组，则其对应的返回值为 Null。

如果路径是受限的语法：
+ 批量字符串，表示弹出的 JSON 值
+ 如果数组为空，则为 Null。
+ 如果路径中的值不是数组，则为 `WRONGTYPE` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRPOP k1 $[*]
1) (nil)
2) "\"a\""
3) "\"b\""
127.0.0.1:6379> JSON.GET k1
"[[],[],[\"a\"]]"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRPOP k1
"[\"a\",\"b\"]"
127.0.0.1:6379> JSON.GET k1
"[[],[\"a\"]]"

127.0.0.1:6379> JSON.SET k2 . '[[], ["a"], ["a", "b"]]'
OK
127.0.0.1:6379> JSON.ARRPOP k2 . 0
"[]"
127.0.0.1:6379> JSON.GET k2
"[[\"a\"],[\"a\",\"b\"]]"
```

# JSON.ARRTRIM
<a name="json-arrtrim"></a>

修剪路径处的数组，以便其成为子数组 [start、end]（两者都包括在内）。
+ 如果该数组为空，则不执行任何操作，返回 0。
+ 如果 start <0，则将其视为 0。
+ 如果 end >= size（数组的大小），则将其视为 size-1。
+ 如果 start >= size 或 start > end，则清空数组并返回 0。

语法

```
JSON.ARRINSERT <key> <path> <start> <end>
```
+ key（必需）– JSON 文档类型的键
+ path（必需）– 一个 JSON 路径
+ start（必需）– 起始索引（含）。
+ end（必需）– 结束索引（含）。

**Return**

如果路径是增强的语法：
+ 表示每个路径处数组的新长度的整数数组。
+ 如果值为空数组，则其对应的返回值为 Null。
+ 如果值不是数组，则其对应的返回值为 Null。
+ 如果有索引参数超出界限，则为 `OUTOFBOUNDARIES` 错误。

如果路径是受限的语法：
+ 整数，该数组的新长度。
+ 如果数组为空，则为 Null。
+ 如果路径中的值不是数组，则为 `WRONGTYPE` 错误。
+ 如果有索引参数超出界限，则为 `OUTOFBOUNDARIES` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[[], ["a"], ["a", "b"], ["a", "b", "c"]]'
OK
127.0.0.1:6379> JSON.ARRTRIM k1 $[*] 0 1
1) (integer) 0
2) (integer) 1
3) (integer) 2
4) (integer) 2
   127.0.0.1:6379> JSON.GET k1
   "[[],[\"a\"],[\"a\",\"b\"],[\"a\",\"b\"]]"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"children": ["John", "Jack", "Tom", "Bob", "Mike"]}'
OK
127.0.0.1:6379> JSON.ARRTRIM k1 .children 0 1
(integer) 2
127.0.0.1:6379> JSON.GET k1 .children
"[\"John\",\"Jack\"]"
```

# JSON.CLEAR
<a name="json-clear"></a>

清除路径中的数组或对象。

语法

```
JSON.CLEAR <key> [path]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**
+ 整数，已清除的容器数量。
+ 清除空数组或对象会导致清除 0 个容器。
**注意**  
在 Redis OSS 版本 6.2.6.R2 之前，清除空数组或对象会导致清除 1 个容器。
+ 清除非容器值会返回 0。
+ 如果路径中未找到任何数组或对象值，则该命令将返回 0。

**示例**

```
127.0.0.1:6379> JSON.SET k1 . '[[], [0], [0,1], [0,1,2], 1, true, null, "d"]'
OK
127.0.0.1:6379>  JSON.CLEAR k1  $[*]
(integer) 6
127.0.0.1:6379> JSON.CLEAR k1  $[*]
(integer) 0
127.0.0.1:6379> JSON.SET k2 . '{"children": ["John", "Jack", "Tom", "Bob", "Mike"]}'
OK
127.0.0.1:6379> JSON.CLEAR k2 .children
(integer) 1
127.0.0.1:6379> JSON.GET k2 .children
"[]"
```

# JSON.DEBUG
<a name="json-debug"></a>

报告信息。支持的子命令有：
+ MEMORY <key> [path] – 报告 JSON 值的内存使用量（以字节为单位）。如果未提供，则路径默认为根目录。
+ DEPTH <key> [path] – 报告 JSON 文档的最大路径深度。
**注意**  
此子命令仅适用于使用 Valkey 7.2 或更高版本，或使用 Redis OSS 引擎版本 6.2.6.R2 或更高版本。
+ FIELDS <key> [path] – 报告指定文档路径中的字段数。如果未提供，则路径默认为根目录。每个非容器 JSON 值均计为一个字段。对象和数组以递归方式为其包含的每个 JSON 值计数一个字段。除根容器外，每个容器值均计为一个额外字段。
+ HELP – 打印命令的帮助消息。

语法

```
JSON.DEBUG <subcommand & arguments>
```

取决于子命令：

MEMORY
+ 如果路径是增强的语法：
  + 返回一个整数数组，该数组表示每个路径处 JSON 值的内存大小（以字节为单位）。
  + 如果键不存在，则返回空数组。
+ 如果路径是受限的语法：
  + 返回整数、内存大小和 JSON 值（以字节为单位）。
  + 如果键不存在，则返回 Null。

DEPTH
+ 返回一个表示 JSON 文档最大路径深度的整数。
+ 如果键不存在，则返回 Null。

FIELDS
+ 如果路径是增强的语法：
  + 返回一个整数数组，该数组表示每个路径中 JSON 值的字段数。
  + 如果键不存在，则返回空数组。
+ 如果路径是受限的语法：
  + 返回一个整数，即 JSON 值的字段数。
  + 如果键不存在，则返回 Null。

HELP – 返回一个帮助消息数组。

**示例**

增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[1, 2.3, "foo", true, null, {}, [], {"a":1, "b":2}, [1,2,3]]'
OK
127.0.0.1:6379> JSON.DEBUG MEMORY k1 $[*]
1) (integer) 16
2) (integer) 16
3) (integer) 19
4) (integer) 16
5) (integer) 16
6) (integer) 16
7) (integer) 16
8) (integer) 50
9) (integer) 64
127.0.0.1:6379> JSON.DEBUG FIELDS k1 $[*]
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 1
5) (integer) 1
6) (integer) 0
7) (integer) 0
8) (integer) 2
9) (integer) 3
```

受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.DEBUG MEMORY k1
(integer) 632
127.0.0.1:6379> JSON.DEBUG MEMORY k1 .phoneNumbers
(integer) 166

127.0.0.1:6379> JSON.DEBUG FIELDS k1
(integer) 19
127.0.0.1:6379> JSON.DEBUG FIELDS k1 .address
(integer) 4

127.0.0.1:6379> JSON.DEBUG HELP
1) JSON.DEBUG MEMORY <key> [path] - report memory size (bytes) of the JSON element. Path defaults to root if not provided.
2) JSON.DEBUG FIELDS <key> [path] - report number of fields in the JSON element. Path defaults to root if not provided.
3) JSON.DEBUG HELP - print help message.
```

# JSON.DEL
<a name="json-del"></a>

删除文档键中路径处的 JSON 值。如果路径是根目录，则相当于从 Valkey 或 Redis OSS 中删除键。

语法

```
JSON.DEL <key> [path]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**
+ 已删除元素的数量。
+ 如果键不存在，则为 0。
+ 如果 JSON 路径无效或不存在，则为 0。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}, "e": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.DEL k1 $.d.*
(integer) 3
127.0.0.1:6379> JSOn.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[1,2,3,4,5]}"
127.0.0.1:6379> JSON.DEL k1 $.e[*]
(integer) 5
127.0.0.1:6379> JSOn.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[]}"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}, "e": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.DEL k1 .d.*
(integer) 3
127.0.0.1:6379> JSON.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[1,2,3,4,5]}"
127.0.0.1:6379> JSON.DEL k1 .e[*]
(integer) 5
127.0.0.1:6379> JSON.GET k1
"{\"a\":{},\"b\":{\"a\":1},\"c\":{\"a\":1,\"b\":2},\"d\":{},\"e\":[]}"
```

# JSON.FORGET
<a name="json-forget"></a>

[JSON.DEL](json-del.md) 的别名

# JSON.GET
<a name="json-get"></a>

返回一个或多个路径的序列化 JSON。

语法

```
JSON.GET <key>
[INDENT indentation-string]
[NEWLINE newline-string]
[SPACE space-string]
[NOESCAPE]
[path ...]
```
+ key（必需）– JSON 文档类型的键
+ INDENT/NEWLINE/SPACE（可选）— 控制返回的 JSON 字符串的格式，即 “漂亮的打印”。每个字符串的默认值都是空字符串。他们在任意组合中都可被覆盖。可以按任意顺序指定这些字符串。
+ NOESCAPE – 可选，允许存在以实现与旧版的兼容性，且没有其他影响。
+ path（可选）– 零个或多个 JSON 路径，如果没有给出，则默认为根目录。路径参数必须放在末尾。

**Return**

增强的路径语法：

 如果给出了一条路径：
+ 返回值数组的序列化字符串。
+ 如果未选择值，则此命令会返回一个空数组。

 如果给出了多条路径：
+ 返回一个字符串化的 JSON 对象，其中的每个路径都是一个键。
+ 如果混合了增强的路径语法和受限的路径语法，则结果符合增强的语法。
+ 如果路径不存在，则其相应的值为空数组。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.GET k1 $.address.*
"[\"21 2nd Street\",\"New York\",\"NY\",\"10021-3100\"]"
127.0.0.1:6379> JSON.GET k1 indent "\t" space " " NEWLINE "\n" $.address.*
"[\n\t\"21 2nd Street\",\n\t\"New York\",\n\t\"NY\",\n\t\"10021-3100\"\n]"
127.0.0.1:6379> JSON.GET k1 $.firstName $.lastName $.age
"{\"$.firstName\":[\"John\"],\"$.lastName\":[\"Smith\"],\"$.age\":[27]}"            
127.0.0.1:6379> JSON.SET k2 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}}'
OK
127.0.0.1:6379> json.get k2 $..*
"[{},{\"a\":1},{\"a\":1,\"b\":2},1,1,2]"
```

 受限的路径语法：

```
 127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.GET k1 .address
"{\"street\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\",\"zipcode\":\"10021-3100\"}"
127.0.0.1:6379> JSON.GET k1 indent "\t" space " " NEWLINE "\n" .address
"{\n\t\"street\": \"21 2nd Street\",\n\t\"city\": \"New York\",\n\t\"state\": \"NY\",\n\t\"zipcode\": \"10021-3100\"\n}"
127.0.0.1:6379> JSON.GET k1 .firstName .lastName .age
"{\".firstName\":\"John\",\".lastName\":\"Smith\",\".age\":27}"
```

# JSON.MGET
<a name="json-mget"></a>

从多个文档密钥 JSONs 在路径上进行序列化。对于不存在的键或 JSON 路径，将返回 null。

语法

```
JSON.MGET <key> [key ...] <path>
```
+ key（必需）– 一个或多个文档类型的键。
+ path（必需）– 一个 JSON 路径

**Return**
+ 批量字符串数组。数组的大小等于命令中的键数。数组中的每个元素都填充有（a）由路径定位的序列化 JSON 或（b）如果键不存在、路径在文档中不存在或路径无效（语法错误），则填充 Null。
+ 如果存在任何指定的键且不是 JSON 键，该命令返回 `WRONGTYPE` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021"}}'
OK
127.0.0.1:6379> JSON.SET k2 . '{"address":{"street":"5 main Street","city":"Boston","state":"MA","zipcode":"02101"}}'
OK
127.0.0.1:6379> JSON.SET k3 . '{"address":{"street":"100 Park Ave","city":"Seattle","state":"WA","zipcode":"98102"}}'
OK
127.0.0.1:6379> JSON.MGET k1 k2 k3 $.address.city
1) "[\"New York\"]"
2) "[\"Boston\"]"
3) "[\"Seattle\"]"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021"}}'
OK
127.0.0.1:6379> JSON.SET k2 . '{"address":{"street":"5 main Street","city":"Boston","state":"MA","zipcode":"02101"}}'
OK
127.0.0.1:6379> JSON.SET k3 . '{"address":{"street":"100 Park Ave","city":"Seattle","state":"WA","zipcode":"98102"}}'
OK

127.0.0.1:6379> JSON.MGET k1 k2 k3 .address.city
1) "\"New York\""
2) "\"Seattle\""
3) "\"Seattle\""
```

# JSON.NUMINCRBY
<a name="json-numincrby"></a>

将路径上的数字值增加给定的数字。

语法

```
JSON.NUMINCRBY <key> <path> <number>
```
+ key（必需）– JSON 文档类型的键
+ path（必需）– 一个 JSON 路径
+ number（必填）– 一个数字

**Return**

如果路径是增强的语法：
+ 表示每个路径的结果值的批量字符串数组。
+ 如果值不是数字，其对应的返回值为 Null。
+ 如果该数字无法解析，则为 `WRONGTYPE` 错误。
+ 如果结果超出 64 位 IEEE 双精度范围，则为 `OVERFLOW` 错误。
+ 如果文档键不存在，则为 `NONEXISTENT`。

如果路径是受限的语法：
+ 表示结果值的批量字符串。
+ 如果选择了多个值，该命令将返回上次更新值的结果。
+ 如果路径中的值不是数字，则为 `WRONGTYPE` 错误。
+ 如果该数字无法解析，则为 `WRONGTYPE` 错误。
+ 如果结果超出 64 位 IEEE 双精度范围，则为 `OVERFLOW` 错误。
+ 如果文档键不存在，则为 `NONEXISTENT`。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k1 $.d[*] 10
"[11,12,13]"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[1],\"c\":[1,2],\"d\":[11,12,13]}"

127.0.0.1:6379> JSON.SET k1 $ '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k1 $.a[*] 1
"[]"
127.0.0.1:6379> JSON.NUMINCRBY k1 $.b[*] 1
"[2]"
127.0.0.1:6379> JSON.NUMINCRBY k1 $.c[*] 1
"[2,3]"
127.0.0.1:6379> JSON.NUMINCRBY k1 $.d[*] 1
"[2,3,4]"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[2,3],\"d\":[2,3,4]}"

127.0.0.1:6379> JSON.SET k2 $ '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k2 $.a.* 1
"[]"
127.0.0.1:6379> JSON.NUMINCRBY k2 $.b.* 1
"[2]"
127.0.0.1:6379> JSON.NUMINCRBY k2 $.c.* 1
"[2,3]"
127.0.0.1:6379> JSON.NUMINCRBY k2 $.d.* 1
"[2,3,4]"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":2,\"b\":3},\"d\":{\"a\":2,\"b\":3,\"c\":4}}"

127.0.0.1:6379> JSON.SET k3 $ '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"b"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k3 $.a.* 1
"[null]"
127.0.0.1:6379> JSON.NUMINCRBY k3 $.b.* 1
"[null,2]"
127.0.0.1:6379> JSON.NUMINCRBY k3 $.c.* 1
"[null,null]"
127.0.0.1:6379> JSON.NUMINCRBY k3 $.d.* 1
"[2,null,4]"
127.0.0.1:6379> JSON.GET k3
"{\"a\":{\"a\":\"a\"},\"b\":{\"a\":\"a\",\"b\":2},\"c\":{\"a\":\"a\",\"b\":\"b\"},\"d\":{\"a\":2,\"b\":\"b\",\"c\":4}}"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k1 .d[1] 10
"12"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[1],\"c\":[1,2],\"d\":[1,12,3]}"

127.0.0.1:6379> JSON.SET k1 . '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k1 .a[*] 1
(error) NONEXISTENT JSON path does not exist
127.0.0.1:6379> JSON.NUMINCRBY k1 .b[*] 1
"2"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[1,2],\"d\":[1,2,3]}"
127.0.0.1:6379> JSON.NUMINCRBY k1 .c[*] 1
"3"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[2,3],\"d\":[1,2,3]}"
127.0.0.1:6379> JSON.NUMINCRBY k1 .d[*] 1
"4"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[2,3],\"d\":[2,3,4]}"

127.0.0.1:6379> JSON.SET k2 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k2 .a.* 1
(error) NONEXISTENT JSON path does not exist
127.0.0.1:6379> JSON.NUMINCRBY k2 .b.* 1
"2"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":1,\"b\":2},\"d\":{\"a\":1,\"b\":2,\"c\":3}}"
127.0.0.1:6379> JSON.NUMINCRBY k2 .c.* 1
"3"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":2,\"b\":3},\"d\":{\"a\":1,\"b\":2,\"c\":3}}"
127.0.0.1:6379> JSON.NUMINCRBY k2 .d.* 1
"4"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":2,\"b\":3},\"d\":{\"a\":2,\"b\":3,\"c\":4}}"

127.0.0.1:6379> JSON.SET k3 . '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"b"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.NUMINCRBY k3 .a.* 1
(error) WRONGTYPE JSON element is not a number
127.0.0.1:6379> JSON.NUMINCRBY k3 .b.* 1
"2"
127.0.0.1:6379> JSON.NUMINCRBY k3 .c.* 1
(error) WRONGTYPE JSON element is not a number
127.0.0.1:6379> JSON.NUMINCRBY k3 .d.* 1
"4"
```

# JSON.NUMMULTBY
<a name="json-nummultby"></a>

将路径上的数值乘以给定的数字。

语法

```
JSON.NUMMULTBY <key> <path> <number>
```
+ key（必需）– JSON 文档类型的键
+ path（必需）– 一个 JSON 路径
+ number（必填）– 一个数字

**Return**

如果路径是增强的语法：
+ 表示每个路径的结果值的批量字符串数组。
+ 如果值不是数字，其对应的返回值为 Null。
+ 如果该数字无法解析，则为 `WRONGTYPE` 错误。
+ 如果结果超出 64 位 IEEE 双精度范围，则为 `OVERFLOW` 错误。
+ 如果文档键不存在，则为 `NONEXISTENT`。

如果路径是受限的语法：
+ 表示结果值的批量字符串。
+ 如果选择了多个值，该命令将返回上次更新值的结果。
+ 如果路径中的值不是数字，则为 `WRONGTYPE` 错误。
+ 如果该数字无法解析，则为 `WRONGTYPE` 错误。
+ 如果结果超出 64 位 IEEE 双精度范围，则为 `OVERFLOW` 错误。
+ 如果文档键不存在，则为 `NONEXISTENT`。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k1 $.d[*] 2
"[2,4,6]"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[1],\"c\":[1,2],\"d\":[2,4,6]}"

127.0.0.1:6379> JSON.SET k1 $ '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k1 $.a[*] 2
"[]"
127.0.0.1:6379> JSON.NUMMULTBY k1 $.b[*] 2
"[2]"
127.0.0.1:6379> JSON.NUMMULTBY k1 $.c[*] 2
"[2,4]"
127.0.0.1:6379> JSON.NUMMULTBY k1 $.d[*] 2
"[2,4,6]"

127.0.0.1:6379> JSON.SET k2 $ '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k2 $.a.* 2
"[]"
127.0.0.1:6379> JSON.NUMMULTBY k2 $.b.* 2
"[2]"
127.0.0.1:6379> JSON.NUMMULTBY k2 $.c.* 2
"[2,4]"
127.0.0.1:6379> JSON.NUMMULTBY k2 $.d.* 2
"[2,4,6]"

127.0.0.1:6379> JSON.SET k3 $ '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"b"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k3 $.a.* 2
"[null]"
127.0.0.1:6379> JSON.NUMMULTBY k3 $.b.* 2
"[null,2]"
127.0.0.1:6379> JSON.NUMMULTBY k3 $.c.* 2
"[null,null]"
127.0.0.1:6379> JSON.NUMMULTBY k3 $.d.* 2
"[2,null,6]"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k1 .d[1] 2
"4"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[1],\"c\":[1,2],\"d\":[1,4,3]}"

127.0.0.1:6379> JSON.SET k1 . '{"a":[], "b":[1], "c":[1,2], "d":[1,2,3]}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k1 .a[*] 2
(error) NONEXISTENT JSON path does not exist
127.0.0.1:6379> JSON.NUMMULTBY k1 .b[*] 2
"2"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[1,2],\"d\":[1,2,3]}"
127.0.0.1:6379> JSON.NUMMULTBY k1 .c[*] 2
"4"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[2,4],\"d\":[1,2,3]}"
127.0.0.1:6379> JSON.NUMMULTBY k1 .d[*] 2
"6"
127.0.0.1:6379> JSON.GET k1
"{\"a\":[],\"b\":[2],\"c\":[2,4],\"d\":[2,4,6]}"

127.0.0.1:6379> JSON.SET k2 . '{"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}, "d":{"a":1, "b":2, "c":3}}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k2 .a.* 2
(error) NONEXISTENT JSON path does not exist
127.0.0.1:6379> JSON.NUMMULTBY k2 .b.* 2
"2"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":1,\"b\":2},\"d\":{\"a\":1,\"b\":2,\"c\":3}}"
127.0.0.1:6379> JSON.NUMMULTBY k2 .c.* 2
"4"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":2,\"b\":4},\"d\":{\"a\":1,\"b\":2,\"c\":3}}"
127.0.0.1:6379> JSON.NUMMULTBY k2 .d.* 2
"6"
127.0.0.1:6379> JSON.GET k2
"{\"a\":{},\"b\":{\"a\":2},\"c\":{\"a\":2,\"b\":4},\"d\":{\"a\":2,\"b\":4,\"c\":6}}"

127.0.0.1:6379> JSON.SET k3 . '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"b"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.NUMMULTBY k3 .a.* 2
(error) WRONGTYPE JSON element is not a number
127.0.0.1:6379> JSON.NUMMULTBY k3 .b.* 2
"2"
127.0.0.1:6379> JSON.GET k3
"{\"a\":{\"a\":\"a\"},\"b\":{\"a\":\"a\",\"b\":2},\"c\":{\"a\":\"a\",\"b\":\"b\"},\"d\":{\"a\":1,\"b\":\"b\",\"c\":3}}"
127.0.0.1:6379> JSON.NUMMULTBY k3 .c.* 2
(error) WRONGTYPE JSON element is not a number
127.0.0.1:6379> JSON.NUMMULTBY k3 .d.* 2
"6"
127.0.0.1:6379> JSON.GET k3
"{\"a\":{\"a\":\"a\"},\"b\":{\"a\":\"a\",\"b\":2},\"c\":{\"a\":\"a\",\"b\":\"b\"},\"d\":{\"a\":2,\"b\":\"b\",\"c\":6}}"
```

# JSON.OBJLEN
<a name="json-objlen"></a>

获取路径对象值中的键数。

语法

```
JSON.OBJLEN <key> [path]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 表示每个路径的对象长度的整数数组。
+ 如果值不是对象，其对应的返回值为 Null。
+ 如果文档键不存在，则为 Null。

如果路径是受限的语法：
+ 整数，对象中的键数。
+ 如果选择了多个对象，该命令将返回第一个对象的长度。
+ 如果路径中的值不是对象，则为 `WRONGTYPE` 错误。
+ 如果路径不存在，则为 `WRONGTYPE` 错误。
+ 如果文档键不存在，则为 Null。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 $ '{"a":{}, "b":{"a":"a"}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":{"a":3,"b":4}}, "e":1}'
OK
127.0.0.1:6379> JSON.OBJLEN k1 $.a
1) (integer) 0
127.0.0.1:6379> JSON.OBJLEN k1 $.a.*
(empty array)
127.0.0.1:6379> JSON.OBJLEN k1 $.b
1) (integer) 1
127.0.0.1:6379> JSON.OBJLEN k1 $.b.*
1) (nil)
127.0.0.1:6379> JSON.OBJLEN k1 $.c
1) (integer) 2
127.0.0.1:6379> JSON.OBJLEN k1 $.c.*
1) (nil)
2) (nil)
127.0.0.1:6379> JSON.OBJLEN k1 $.d
1) (integer) 3
127.0.0.1:6379> JSON.OBJLEN k1 $.d.*
1) (nil)
2) (nil)
3) (integer) 2
127.0.0.1:6379> JSON.OBJLEN k1 $.*
1) (integer) 0
2) (integer) 1
3) (integer) 2
4) (integer) 3
5) (nil)
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":{}, "b":{"a":"a"}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":{"a":3,"b":4}}, "e":1}'
OK
127.0.0.1:6379> JSON.OBJLEN k1 .a
(integer) 0
127.0.0.1:6379> JSON.OBJLEN k1 .a.*
(error) NONEXISTENT JSON path does not exist
127.0.0.1:6379> JSON.OBJLEN k1 .b
(integer) 1
127.0.0.1:6379> JSON.OBJLEN k1 .b.*
(error) WRONGTYPE JSON element is not an object
127.0.0.1:6379> JSON.OBJLEN k1 .c
(integer) 2
127.0.0.1:6379> JSON.OBJLEN k1 .c.*
(error) WRONGTYPE JSON element is not an object
127.0.0.1:6379> JSON.OBJLEN k1 .d
(integer) 3
127.0.0.1:6379> JSON.OBJLEN k1 .d.*
(integer) 2
127.0.0.1:6379> JSON.OBJLEN k1 .*
(integer) 0
```

# JSON.OBJKEYS
<a name="json-objkeys"></a>

获取路径对象值中的键名。

语法

```
JSON.OBJKEYS <key> [path]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 批量字符串数组的数组。每个元素都是匹配对象中的键数组。
+ 如果值不是对象，其对应的返回值为空值。
+ 如果文档键不存在，则为 Null。

如果路径是受限的语法：
+ 批量字符串数组。每个元素都是对象中的键名称。
+ 如果选择了多个对象，该命令将返回第一个对象的键。
+ 如果路径中的值不是对象，则为 `WRONGTYPE` 错误。
+ 如果路径不存在，则为 `WRONGTYPE` 错误。
+ 如果文档键不存在，则为 Null。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 $ '{"a":{}, "b":{"a":"a"}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":{"a":3,"b":4}}, "e":1}'
OK
127.0.0.1:6379> JSON.OBJKEYS k1 $.*
1) (empty array)
2) 1) "a"
3) 1) "a"
   2) "b"
4) 1) "a"
   2) "b"
   3) "c"
5) (empty array)
127.0.0.1:6379> JSON.OBJKEYS k1 $.d
1) 1) "a"
   2) "b"
   3) "c"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 $ '{"a":{}, "b":{"a":"a"}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":{"a":3,"b":4}}, "e":1}'
OK
127.0.0.1:6379> JSON.OBJKEYS k1 .*
1) "a"
127.0.0.1:6379> JSON.OBJKEYS k1 .d
1) "a"
2) "b"
3) "c"
```

# JSON.RESP
<a name="json-resp"></a>

返回 Valkey 或 Redis OSS 序列化协议（RESP）中给定路径的 JSON 值。如果值为容器，则响应为 RESP 数组或嵌套数组。
+ JSON 空值映射到 RESP Null 批量字符串。
+ JSON 布尔值映射到相应的 RESP 简单字符串。
+ 整数被映射到 RESP 整数。
+ 64 位 IEEE 双浮点数映射到 RESP 批量字符串。
+ JSON 字符串被映射到 RESP 批量字符串。
+ JSON 数组表示为 RESP 数组，其中第一个元素是简单字符串 [，然后是数组的元素。
+ JSON 对象表示为 RESP 数组，其中第一个元素是简单字符串 \$1，然后是键值对，每个键值对都是 RESP 批量字符串。

语法

```
JSON.RESP <key> [path]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 数组的数组。每个数组元素都代表一个路径上值的 RESP 形式。
+ 如果文档键不存在，则为空数组。

如果路径是受限的语法：
+ 表示路径中值的 RESP 形式的数组。
+ 如果文档键不存在，则为 Null。

**示例**

增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK

127.0.0.1:6379> JSON.RESP k1 $.address
1) 1) {
   2) 1) "street"
      2) "21 2nd Street"
   3) 1) "city"
      2) "New York"
   4) 1) "state"
      2) "NY"
   5) 1) "zipcode"
      2) "10021-3100"

127.0.0.1:6379> JSON.RESP k1 $.address.*
1) "21 2nd Street"
2) "New York"
3) "NY"
4) "10021-3100"

127.0.0.1:6379> JSON.RESP k1 $.phoneNumbers
1) 1) [
   2) 1) {
      2) 1) "type"
         2) "home"
      3) 1) "number"
         2) "555 555-1234"
   3) 1) {
      2) 1) "type"
         2) "office"
      3) 1) "number"
         2) "555 555-4567"

127.0.0.1:6379> JSON.RESP k1 $.phoneNumbers[*]
1) 1) {
   2) 1) "type"
      2) "home"
   3) 1) "number"
      2) "212 555-1234"
2) 1) {
   2) 1) "type"
      2) "office"
   3) 1) "number"
      2) "555 555-4567"
```

受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK

127.0.0.1:6379> JSON.RESP k1 .address
1) {
2) 1) "street"
   2) "21 2nd Street"
3) 1) "city"
   2) "New York"
4) 1) "state"
   2) "NY"
5) 1) "zipcode"
   2) "10021-3100"

127.0.0.1:6379> JSON.RESP k1
 1) {
 2) 1) "firstName"
    2) "John"
 3) 1) "lastName"
    2) "Smith"
 4) 1) "age"
    2) (integer) 27
 5) 1) "weight"
    2) "135.25"
 6) 1) "isAlive"
    2) true
 7) 1) "address"
    2) 1) {
       2) 1) "street"
          2) "21 2nd Street"
       3) 1) "city"
          2) "New York"
       4) 1) "state"
          2) "NY"
       5) 1) "zipcode"
          2) "10021-3100"
 8) 1) "phoneNumbers"
    2) 1) [
       2) 1) {
          2) 1) "type"
             2) "home"
          3) 1) "number"
             2) "212 555-1234"
       3) 1) {
          2) 1) "type"
             2) "office"
          3) 1) "number"
             2) "555 555-4567"
 9) 1) "children"
    2) 1) [
10) 1) "spouse"
    2) (nil)
```

# JSON.SET
<a name="json-set"></a>

在路径中设置 JSON 值。

如果路径调用对象成员：
+ 如果父元素不存在，该命令将返回 NONEXISTENT 错误。
+ 如果父元素存在但不是对象，该命令将返回 ERROR。
+ 如果父元素存在并且是对象：
  +  如果成员不存在，当且仅当父对象是路径中的最后一个子对象时，才会将新成员附加到父对象。否则，该命令将返回 NONEXISTENT 错误。
  +  如果成员存在，则其值将替换为 JSON 值。

如果路径调用数组索引：
+ 如果父元素不存在，该命令将返回 NONEXISTENT 错误。
+ 如果父元素存在但不是数组，该命令将返回 ERROR。
+ 如果父元素存在但索引超出界限，该命令返回 OUTOFBOUNDARIES 错误。
+ 如果父元素存在且索引有效，该元素将被新的 JSON 值替换。

如果路径调用对象或数组，该值（对象或数组）将被新的 JSON 值替换。

语法

```
JSON.SET <key> <path> <json> [NX | XX] 
```

[NX \$1 XX]，其中您可以有 0 或 1 个 [NX \$1 XX] 标识符
+ key（必需）– JSON 文档类型的键
+ path（必需）– JSON 路径。对于新的键，JSON 路径必须是根目录“.”。
+ NX（可选）– 如果路径是根目录，仅在键不存在时设置该值，即插入新文档。如果路径不是根目录，仅在路径不存在时设置该值，即在文档中插入一个值。
+ XX（可选）– 如果路径是根目录，仅在键存在时设置该值，即替换现有文档。如果路径不是根目录，则仅在路径存在时设置该值，即更新现有值。

**Return**
+ 成功时使用简单字符串“OK”。
+ 如果未满足 NX 或 XX 条件，则为 Null。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":{"a":1, "b":2, "c":3}}'
OK
127.0.0.1:6379> JSON.SET k1 $.a.* '0'
OK
127.0.0.1:6379> JSON.GET k1
"{\"a\":{\"a\":0,\"b\":0,\"c\":0}}"

127.0.0.1:6379> JSON.SET k2 . '{"a": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.SET k2 $.a[*] '0'
OK
127.0.0.1:6379> JSON.GET k2
"{\"a\":[0,0,0,0,0]}"
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"c":{"a":1, "b":2}, "e": [1,2,3,4,5]}'
OK
127.0.0.1:6379> JSON.SET k1 .c.a '0'
OK
127.0.0.1:6379> JSON.GET k1
"{\"c\":{\"a\":0,\"b\":2},\"e\":[1,2,3,4,5]}"
127.0.0.1:6379> JSON.SET k1 .e[-1] '0'
OK
127.0.0.1:6379> JSON.GET k1
"{\"c\":{\"a\":0,\"b\":2},\"e\":[1,2,3,4,0]}"
127.0.0.1:6379> JSON.SET k1 .e[5] '0'
(error) OUTOFBOUNDARIES Array index is out of bounds
```

# JSON.STRAPPEND
<a name="json-strappend"></a>

将字符串附加到路径的 JSON 字符串。

语法

```
JSON.STRAPPEND <key> [path] <json_string>
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录
+ json\$1string（必需）– 字符串的 JSON 表示。请注意，JSON 字符串必须用引号括起来，即'"foo"'。

**Return**

如果路径是增强的语法：
+ 表示每个路径字符串的新长度的整数数组。
+ 如果路径上的值不是字符串，其对应的返回值为 Null。
+ 如果输入 json 参数不是有效的 JSON 字符串，则为 `SYNTAXERR ` 错误。
+ 如果路径不存在，则为 `NONEXISTENT ` 错误。

如果路径是受限的语法：
+ 整数，该字符串的新长度。
+ 如果选择了多个字符串值，该命令将返回上次更新字符串的新长度。
+ 如果路径中的值不是字符串，则为 `WRONGTYPE` 错误。
+ 如果输入 json 参数不是有效的 JSON 字符串，则为 `WRONGTYPE` 错误。
+ 如果路径不存在，则为 `NONEXISTENT` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 $ '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.STRAPPEND k1 $.a.a '"a"'
1) (integer) 2
127.0.0.1:6379> JSON.STRAPPEND k1 $.a.* '"a"'
1) (integer) 3
127.0.0.1:6379> JSON.STRAPPEND k1 $.b.* '"a"'
1) (integer) 2
2) (nil)
127.0.0.1:6379> JSON.STRAPPEND k1 $.c.* '"a"'
1) (integer) 2
2) (integer) 3
127.0.0.1:6379> JSON.STRAPPEND k1 $.c.b '"a"'
1) (integer) 4
127.0.0.1:6379> JSON.STRAPPEND k1 $.d.* '"a"'
1) (nil)
2) (integer) 2
3) (nil)
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.STRAPPEND k1 .a.a '"a"'
(integer) 2
127.0.0.1:6379> JSON.STRAPPEND k1 .a.* '"a"'
(integer) 3
127.0.0.1:6379> JSON.STRAPPEND k1 .b.* '"a"'
(integer) 2
127.0.0.1:6379> JSON.STRAPPEND k1 .c.* '"a"'
(integer) 3
127.0.0.1:6379> JSON.STRAPPEND k1 .c.b '"a"'
(integer) 4
127.0.0.1:6379> JSON.STRAPPEND k1 .d.* '"a"'
(integer) 2
```

# JSON.STRLEN
<a name="json-strlen"></a>

获取路径中 JSON 字符串值的长度。

语法

```
JSON.STRLEN <key> [path] 
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 表示每个路径的字符串值长度的整数数组。
+ 如果值不是字符串，其对应的返回值为 Null。
+ 如果文档键不存在，则为 Null。

如果路径是受限的语法：
+ 整数，该字符串的长度。
+ 如果选择了多个字符串值，该命令将返回第一个字符串的长度。
+ 如果路径中的值不是字符串，则为 `WRONGTYPE` 错误。
+ 如果路径不存在，则为 `NONEXISTENT` 错误。
+ 如果文档键不存在，则为 Null。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 $ '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.STRLEN k1 $.a.a
1) (integer) 1
127.0.0.1:6379> JSON.STRLEN k1 $.a.*
1) (integer) 1
127.0.0.1:6379> JSON.STRLEN k1 $.c.*
1) (integer) 1
2) (integer) 2
127.0.0.1:6379> JSON.STRLEN k1 $.c.b
1) (integer) 2
127.0.0.1:6379> JSON.STRLEN k1 $.d.*
1) (nil)
2) (integer) 1
3) (nil)
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 $ '{"a":{"a":"a"}, "b":{"a":"a", "b":1}, "c":{"a":"a", "b":"bb"}, "d":{"a":1, "b":"b", "c":3}}'
OK
127.0.0.1:6379> JSON.STRLEN k1 .a.a
(integer) 1
127.0.0.1:6379> JSON.STRLEN k1 .a.*
(integer) 1
127.0.0.1:6379> JSON.STRLEN k1 .c.*
(integer) 1
127.0.0.1:6379> JSON.STRLEN k1 .c.b
(integer) 2
127.0.0.1:6379> JSON.STRLEN k1 .d.*
(integer) 1
```

# JSON.TOGGLE
<a name="json-toggle"></a>

在路径的 true 和 false 之间切换布尔值。

语法

```
JSON.TOGGLE <key> [path] 
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 表示每个路径的结果布尔值的整数数组（0 – false, 1 – true）。
+ 如果值不是布尔值，其对应的返回值为 Null。
+ 如果文档键不存在，则为 `NONEXISTENT`。

如果路径是受限的语法：
+ 表示结果布尔值的字符串 （"true"/"false")。
+ 如果文档键不存在，则为 `NONEXISTENT`。
+ 如果路径中的值不是布尔值，则为 `WRONGTYPE` 错误。

**示例**

 增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"a":true, "b":false, "c":1, "d":null, "e":"foo", "f":[], "g":{}}'
OK
127.0.0.1:6379> JSON.TOGGLE k1 $.*
1) (integer) 0
2) (integer) 1
3) (nil)
4) (nil)
5) (nil)
6) (nil)
7) (nil)
127.0.0.1:6379> JSON.TOGGLE k1 $.*
1) (integer) 1
2) (integer) 0
3) (nil)
4) (nil)
5) (nil)
6) (nil)
7) (nil)
```

 受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . true
OK
127.0.0.1:6379> JSON.TOGGLE k1
"false"
127.0.0.1:6379> JSON.TOGGLE k1
"true"

127.0.0.1:6379> JSON.SET k2 . '{"isAvailable": false}'
OK
127.0.0.1:6379> JSON.TOGGLE k2 .isAvailable
"true"
127.0.0.1:6379> JSON.TOGGLE k2 .isAvailable
"false"
```

# JSON.TYPE
<a name="json-type"></a>

报告给定路径的值类型。

语法

```
JSON.TYPE <key> [path]
```
+ key（必需）– JSON 文档类型的键
+ path（可选）– 一个 JSON 路径。如果未提供，则默认为根目录

**Return**

如果路径是增强的语法：
+ 表示每个路径的值类型的字符串数组。类型为 \$1"null"、"boolean"、"string"、"number"、"integer"、"object" 和 "array"\$1 之一。
+ 如果路径不存在，则其相应的返回值为 Null。
+ 如果文档键不存在，则为空数组。

如果路径是受限的语法：
+ 字符串，值的类型
+ 如果文档键不存在，则为 Null。
+ 如果 JSON 路径无效或不存在，则为 Null。

**示例**

增强的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '[1, 2.3, "foo", true, null, {}, []]'
OK
127.0.0.1:6379> JSON.TYPE k1 $[*]
1) integer
2) number
3) string
4) boolean
5) null
6) object
7) array
```

受限的路径语法：

```
127.0.0.1:6379> JSON.SET k1 . '{"firstName":"John","lastName":"Smith","age":27,"weight":135.25,"isAlive":true,"address":{"street":"21 2nd Street","city":"New York","state":"NY","zipcode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"}],"children":[],"spouse":null}'
OK
127.0.0.1:6379> JSON.TYPE k1
object
127.0.0.1:6379> JSON.TYPE k1 .children
array
127.0.0.1:6379> JSON.TYPE k1 .firstName
string
127.0.0.1:6379> JSON.TYPE k1 .age
integer
127.0.0.1:6379> JSON.TYPE k1 .weight
number
127.0.0.1:6379> JSON.TYPE k1 .isAlive
boolean
127.0.0.1:6379> JSON.TYPE k1 .spouse
null
```