

# Getting started with JSON for Valkey and Redis OSS
<a name="json-gs"></a>

ElastiCache supports the native JavaScript Object Notation (JSON) format, which is a simple, schemaless way to encode complex datasets inside Valkey and Redis OSS clusters. You can natively store and access data using the JavaScript Object Notation (JSON) format inside the clusters, and update JSON data stored in those clusters—without needing to manage custom code to serialize and deserialize it.

In addition to using Valkey and Redis OSS API operations for applications that operate over JSON, you can now efficiently retrieve and update specific portions of a JSON document without needing to manipulate the entire object. This can improve performance and reduce cost. You can also search your JSON document contents using the [Goessner-style](https://goessner.net/articles/JsonPath/) `JSONPath` query. 

After you create a cluster with a supported engine version, the JSON data type and associated commands are automatically available. API compatible and RDB compatible with version 2 of the JSON module, so you can easily migrate existing JSON-based Valkey and Redis OSS applications into ElastiCache. For more information on the supported commands, see [Supported Valkey and Redis OSS commandsJSON commands](json-list-commands.md).

The JSON-related metrics `JsonBasedCmds` and `JsonBasedCmdsLatency` are incorporated into CloudWatch to monitor the usage of this data type. For more information, see [Metrics for Valkey and Redis OSS](CacheMetrics.Redis.md).

**Note**  
To use JSON, you must be running Valkey 7.2 and later, or Redis OSS 6.2.6 or later.

**Topics**
+ [JSON data type overview](json-document-overview.md)
+ [Supported Valkey and Redis OSS commands](json-list-commands.md)

# JSON data type overview
<a name="json-document-overview"></a>

ElastiCache supports a number of Valkey and Redis OSS commands for working with the JSON data type. The following is an overview of the JSON data type and a detailed list of commands that are supported.

## Terminology
<a name="json-terminology"></a>


****  

| Term | Description | 
| --- | --- | 
|  JSON document | Refers to the value of a JSON key. | 
|  JSON value | Refers to a subset of a JSON document, including the root that represents the entire document. A value could be a container or an entry within a container. | 
|  JSON element | Equivalent to JSON value. | 

## Supported JSON standard
<a name="Supported-JSON-Standard"></a>

JSON format is compliant with [RFC 7159](https://www.ietf.org/rfc/rfc7159.txt) and [ECMA-404](https://www.ietf.org/rfc/rfc7159.txt) JSON data interchange standard. UTF-8 [Unicode](https://www.unicode.org/standard/WhatIsUnicode.html) in JSON text is supported.

## Root element
<a name="json-root-element"></a>

The root element can be of any JSON data type. Note that in earlier RFC 4627, only objects or arrays were allowed as root values. Since the update to RFC 7159, the root of a JSON document can be of any JSON data type.

## Document size limit
<a name="json-document-size-limit"></a>

JSON documents are stored internally in a format that's optimized for rapid access and modification. This format typically results in consuming somewhat more memory than the equivalent serialized representation of the same document. 

The consumption of memory by a single JSON document is limited to 64 MB, which is the size of the in-memory data structure, not the JSON string. You can check the amount of memory consumed by a JSON document by using the `JSON.DEBUG MEMORY` command.

## JSON ACLs
<a name="json-acls"></a>
+ Similar to the existing per-datatype categories (@string, @hash, etc.), a new category @json is added to simplify managing access to JSON commands and data. No other existing Valkey or Redis OSS commands are members of the @json category. All JSON commands enforce any keyspace or command restrictions and permissions.
+ There are five existing Valkey and Redis OSS ACL categories that are updated to include the new JSON commands: @read, @write, @fast, @slow and @admin. The following table indicates the mapping of JSON commands to the appropriate categories.


**ACL**  

| JSON command | @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 |  |  | 

## Nesting depth limit
<a name="json-nesting-depth-limit"></a>

When a JSON object or array has an element that is itself another JSON object or array, that inner object or array is said to “nest” within the outer object or array. The maximum nesting depth limit is 128. Any attempt to create a document that contains a nesting depth greater than 128 will be rejected with an error.

## Command syntax
<a name="json-command-syntax"></a>

Most commands require a key name as the first argument. Some commands also have a path argument. The path argument defaults to the root if it's optional and not provided.

 Notation:
+ Required arguments are enclosed in angle brackets. For example: <key>
+ Optional arguments are enclosed in square brackets. For example: [path]
+ Additional optional arguments are indicated by an ellipsis ("…"). For example: [json ...]

## Path syntax
<a name="json-path-syntax"></a>

Redis JSON supports two kinds of path syntaxes:
+ **Enhanced syntax** – Follows the JSONPath syntax described by [Goessner](https://goessner.net/articles/JsonPath/), as shown in the following table. We've reordered and modified the descriptions in the table for clarity.
+ **Restricted syntax** – Has limited query capabilities.

**Note**  
Results of some commands are sensitive to which type of path syntax is used.

 If a query path starts with '\$1', it uses the enhanced syntax. Otherwise, the restricted syntax is used.

**Enhanced syntax**


****  

| Symbol/Expression | Description | 
| --- | --- | 
|  \$1 | The root element. | 
|  . or [] | Child operator. | 
|  .. | Recursive descent. | 
|  \$1 | Wildcard. All elements in an object or array. | 
|  [] | Array subscript operator. Index is 0-based. | 
|  [,] | Union operator. | 
|  [start:end:step] | Array slice operator. | 
|  ?() | Applies a filter (script) expression to the current array or object. | 
|  () | Filter expression. | 
|  @ | Used in filter expressions that refer to the current node being processed. | 
|  == | Equal to, used in filter expressions. | 
|  \$1= | Not equal to, used in filter expressions. | 
|  > | Greater than, used in filter expressions. | 
|  >= | Greater than or equal to, used in filter expressions.  | 
|  < | Less than, used in filter expressions. | 
|  <= | Less than or equal to, used in filter expressions.  | 
|  && | Logical AND, used to combine multiple filter expressions. | 
|  \$1\$1 | Logical OR, used to combine multiple filter expressions. | 

**Examples**

The following examples are built on [Goessner's](https://goessner.net/articles/JsonPath/) example XML data, which we have modified by adding additional fields.

```
{ "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
    }
  }
}
```


****  

| Path | Description | 
| --- | --- | 
|  \$1.store.book[\$1].author | The authors of all books in the store. | 
|  \$1..author | All authors. | 
|  \$1.store.\$1 | All members of the store. | 
|  \$1["store"].\$1 | All members of the store. | 
|  \$1.store..price | The price of everything in the store. | 
|  \$1..\$1 | All recursive members of the JSON structure. | 
|  \$1..book[\$1] | All books. | 
|  \$1..book[0] | The first book. | 
|  \$1..book[-1] | The last book. | 
|  \$1..book[0:2] | The first two books. | 
|  \$1..book[0,1] | The first two books. | 
|  \$1..book[0:4] | Books from index 0 to 3 (ending index is not inclusive). | 
|  \$1..book[0:4:2] | Books at index 0, 2. | 
|  \$1..book[?(@.isbn)] | All books with an ISBN number. | 
|  \$1..book[?(@.price<10)] | All books cheaper than \$110. | 
|  '\$1..book[?(@.price < 10)]' | All books cheaper than \$110. (The path must be quoted if it contains white spaces.) | 
|  '\$1..book[?(@["price"] < 10)]' | All books cheaper than \$110. | 
|  '\$1..book[?(@.["price"] < 10)]' | All books cheaper than \$110. | 
|  \$1..book[?(@.price>=10&&@.price<=100)] | All books in the price range of \$110 to \$1100, inclusive. | 
|  '\$1..book[?(@.price>=10 && @.price<=100)]' | All books in the price range of \$110 to \$1100, inclusive. (The path must be quoted if it contains white spaces.) | 
|  \$1..book[?(@.sold==true\$1\$1@.in-stock==false)] | All books sold or out of stock. | 
|  '\$1..book[?(@.sold == true \$1\$1 @.in-stock == false)]' | All books sold or out of stock. (The path must be quoted if it contains white spaces.) | 
|  '\$1.store.book[?(@.["category"] == "fiction")]' | All books in the fiction category. | 
|  '\$1.store.book[?(@.["category"] \$1= "fiction")]' | All books in nonfiction categories. | 

Additional filter expression examples:

```
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]"
```

**Restricted syntax**


****  

| Symbol/Expression | Description | 
| --- | --- | 
|  . or [] | Child operator. | 
|  [] | Array subscript operator. Index is 0-based. | 

**Examples**


****  

| Path | Description | 
| --- | --- | 
|  .store.book[0].author | The author of the first book. | 
|  .store.book[-1].author | The author of the last book. | 
|  .address.city | City name. | 
|  ["store"]["book"][0]["title"] | The title of the first book. | 
|  ["store"]["book"][-1]["title"] | The title of the last book. | 

**Note**  
All [Goessner](https://goessner.net/articles/JsonPath/) content cited in this documentation is subject to the [Creative Commons License](https://creativecommons.org/licenses/by/2.5/).

## Common error prefixes
<a name="json-error-prefixes"></a>

Each error message has a prefix. The following is a list of common error prefixes.


****  

| Prefix | Description | 
| --- | --- | 
|  ERR | A general error. | 
|  LIMIT | An error that occurs when the size limit is exceeded. For example, the document size limit or nesting depth limit was exceeded. | 
|  NONEXISTENT | A key or path does not exist. | 
|  OUTOFBOUNDARIES | Array index out of bounds. | 
|  SYNTAXERR | Syntax error. | 
|  WRONGTYPE | Wrong value type. | 

## JSON-related metrics
<a name="json-info-metrics"></a>

The following JSON info metrics are provided:


****  

| Info | Description | 
| --- | --- | 
|  json\$1total\$1memory\$1bytes | Total memory allocated to JSON objects. | 
|  json\$1num\$1documents | Total number of documents in Valkey or Redis OSS. | 

To query core metrics, run the following command:

```
info json_core_metrics
```

## How ElastiCache for Valkey and Redis OSS interacts with JSON
<a name="json-differences"></a>

The following section describes how ElastiCache for Valkey and Redis OSS interacts with the JSON data type.

### Operator precedence
<a name="json-operator-precedence"></a>

When evaluating conditional expressions for filtering, &&s take precedence first, and then \$1\$1s are evaluated, as is common across most languages. Operations inside of parentheses are run first. 

### Maximum path nesting limit behavior
<a name="json-max-path"></a>

 The maximum path nesting limit in ElastiCache for Redis OSS is 128. So a value like `$.a.b.c.d...` can only reach 128 levels. 

### Handling numeric values
<a name="json-about-numbers"></a>

JSON doesn't have separate data types for integers and floating point numbers. They are all called numbers.

Numerical representations:

When a JSON number is received on input, it is converted into one of the two internal binary representations: a 64-bit signed integer or a 64-bit IEEE double precision floating point. The original string and all of its formatting are not retained. Thus, when a number is output as part of a JSON response, it is converted from the internal binary representation to a printable string that uses generic formatting rules. These rules might result in a different string being generated than was received.

Arithmetic commands `NUMINCRBY` and `NUMMULTBY`:
+ If both numbers are integers and the result is out of the range of `int64`, it automatically becomes a 64-bit IEEE double precision floating point number.
+ If at least one of the numbers is a floating point, the result is a 64-bit IEEE double precision floating point number.
+ If the result exceeds the range of 64-bit IEEE double, the command returns an `OVERFLOW` error.

For a detailed list of available commands, see [Supported Valkey and Redis OSS commandsJSON commands](json-list-commands.md).

### Direct array filtering
<a name="json-direct-array-filtering"></a>

ElastiCache for Valkey or Redis OSS filters array objects directly.

For data like `[0,1,2,3,4,5,6]` and a path query like `$[?(@<4)]`, or data like `{"my_key":[0,1,2,3,4,5,6]}` and a path query like `$.my_key[?(@<4)]`, ElastiCache would return [1,2,3] in both circumstances. 

### Array indexing behavior
<a name="json-direct-array-indexing"></a>

ElastiCache for Valkey or Redis OSS allows both positive and negative indexes for arrays. For an array of length five, 0 would query the first element, 1 the second, and so on. Negative numbers start at the end of the array, so -1 would query the fifth element, -2 the fourth element, and so on.

To ensure predictable behavior for customers, ElastiCache does not round array indexes down or up, so if you have an array with a length of 5, calling index 5 or higher, or -6 or lower, would not produce a result.

### Strict syntax evaluation
<a name="json-strict-syntax-evaluation"></a>

MemoryDB does not allow JSON paths with invalid syntax, even if a subset of the path contains a valid path. This is to maintain correct behavior for our customers.

# Supported Valkey and Redis OSS commands
<a name="json-list-commands"></a>

ElastiCache supports the following Valkey and Redis OSS JSON commands:

**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.MSET](json-mset.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>

Appends one or more values to the array values at the path.

Syntax

```
JSON.ARRAPPEND <key> <path> <json> [json ...]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path.
+ json (required) – The JSON value to be appended to the array.

**Return**

If the path is enhanced syntax:
+ Array of integers that represent the new length of the array at each path.
+ If a value is not an array, its corresponding return value is null.
+ `NONEXISTENT` error if the path does not exist.

If the path is restricted syntax:
+ Integer, the array's new length.
+ If multiple array values are selected, the command returns the new length of the first updated array.
+ `WRONGTYPE` error if the value at the path is not an array.
+ `SYNTAXERR` error if one of the input json arguments is not a valid JSON string.
+ `NONEXISTENT` error if the path does not exist.

**Examples**

 Enhanced path syntax:

```
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\"]]"
```

 Restricted path syntax:

```
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>

Searches for the first occurrence of a scalar JSON value in the arrays at the path.
+ Out of range errors are treated by rounding the index to the array's start and end.
+ If start > end, return -1 (not found).

Syntax

```
JSON.ARRINDEX <key> <path> <json-scalar> [start [end]]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path.
+ json-scalar (required) – The scalar value to search for. JSON scalar refers to values that are not objects or arrays. That is, string, number, Boolean, and null are scalar values.
+ start (optional) – The start index, inclusive. Defaults to 0 if not provided.
+ end (optional) – The end index, exclusive. Defaults to 0 if not provided, which means that the last element is included. 0 or -1 means the last element is included.

**Return**

If the path is enhanced syntax:
+ Array of integers. Each value is the index of the matching element in the array at the path. The value is -1 if not found.
+ If a value is not an array, its corresponding return value is null.

If the path is restricted syntax:
+ Integer, the index of matching element, or -1 if not found.
+ `WRONGTYPE` error if the value at the path is not an array.

**Examples**

 Enhanced path syntax:

```
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
```

 Restricted path syntax:

```
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>

Inserts one or more values into the array values at the path before the index.

Syntax

```
JSON.ARRINSERT <key> <path> <index> <json> [json ...]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path.
+ index (required) – An array index before which values are inserted.
+ json (required) – The JSON value to be appended to the array.

**Return**

If the path is enhanced syntax:
+ Array of integers that represent the new length of the array at each path.
+ If a value is an empty array, its corresponding return value is null.
+ If a value is not an array, its corresponding return value is null.
+ `OUTOFBOUNDARIES` error if the index argument is out of bounds.

If the path is restricted syntax:
+ Integer, the new length of the array.
+ `WRONGTYPE` error if the value at the path is not an array.
+ `OUTOFBOUNDARIES` error if the index argument is out of bounds.

**Examples**

 Enhanced path syntax:

```
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\"]]"
```

 Restricted path syntax:

```
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>

Gets the length of the array values at the path.

Syntax

```
JSON.ARRLEN <key> [path] 
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of integers that represent the array length at each path.
+ If a value is not an array, its corresponding return value is null.
+ Null if the document key does not exist.

If the path is restricted syntax:
+ Integer, array length.
+ If multiple objects are selected, the command returns the first array's length.
+ `WRONGTYPE` error if the value at the path is not an array.
+ `NONEXISTENT JSON` error if the path does not exist.
+ Null if the document key does not exist.

**Examples**

 Enhanced path syntax:

```
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)
```

 Restricted path syntax:

```
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 [1] 
(integer) 1 
127.0.0.1:6379> JSON.ARRLEN k1 [2] 
(integer) 2

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] 
(error) WRONGTYPE JSON element is not an array 
127.0.0.1:6379> JSON.ARRLEN k2 [0] 
(integer) 0
127.0.0.1:6379> JSON.ARRLEN k2 [6] 
(error) OUTOFBOUNDARIES Array index is out of bounds
127.0.0.1:6379> JSON.ARRLEN k2 a.b 
(error) NONEXISTENT JSON path does not exist
```

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

Removes and returns element at the index from the array. Popping an empty array returns null.

Syntax

```
JSON.ARRPOP <key> [path [index]]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.
+ index (optional) – The position in the array to start popping from.
  + Defaults to -1 if not provided, which means the last element.
  + Negative value means position from the last element.
  + Out of boundary indexes are rounded to their respective array boundaries.

**Return**

If the path is enhanced syntax:
+ Array of bulk strings that represent popped values at each path.
+ If a value is an empty array, its corresponding return value is null.
+ If a value is not an array, its corresponding return value is null.

If the path is restricted syntax:
+ Bulk string, which represents the popped JSON value.
+ Null if the array is empty.
+ `WRONGTYPE` error if the value at the path is not an array.

**Examples**

 Enhanced path syntax:

```
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\"]]"
```

 Restricted path syntax:

```
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>

Trims an arrays at the path so that it becomes a subarray [start, end], both inclusive.
+ If the array is empty, do nothing, return 0.
+ If start <0, treat it as 0.
+ If end >= size (size of the array), treat it as size-1.
+ If start >= size or start > end, empty the array and return 0.

Syntax

```
JSON.ARRTRIM <key> <path> <start> <end>
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path.
+ start (required) – The start index, inclusive.
+ end (required) – The end index, inclusive.

**Return**

If the path is enhanced syntax:
+ Array of integers that represent the new length of the array at each path.
+ If a value is an empty array, its corresponding return value is null.
+ If a value is not an array, its corresponding return value is null.
+ `OUTOFBOUNDARIES` error if an index argument is out of bounds.

If the path is restricted syntax:
+ Integer, the new length of the array.
+ Null if the array is empty.
+ `WRONGTYPE` error if the value at the path is not an array.
+ `OUTOFBOUNDARIES` error if an index argument is out of bounds.

**Examples**

 Enhanced path syntax:

```
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\"]]"
```

 Restricted path syntax:

```
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>

Clears the arrays or an object at the path.

Syntax

```
JSON.CLEAR <key> [path]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**
+ Integer, the number of containers cleared.
+ Clearing an empty array or object accounts for 1 container cleared.
+ Clearing a non-container value returns 0.

**Examples**

```
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) 7
127.0.0.1:6379> JSON.CLEAR k1  $[*]
(integer) 4
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>

Reports information. Supported subcommands are:
+ MEMORY <key> [path] – Reports memory usage in bytes of a JSON value. Path defaults to the root if not provided.
+ FIELDS <key> [path] – Reports the number of fields at the specified document path. Path defaults to the root if not provided. Each non-container JSON value counts as one field. Objects and arrays recursively count one field for each of their containing JSON values. Each container value, except the root container, counts as one additional field.
+ HELP – Prints help messages of the command.

Syntax

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

Depends on the subcommand:

MEMORY
+ If the path is enhanced syntax:
  + Returns an array of integers that represent memory size (in bytes) of JSON value at each path.
  + Returns an empty array if the Valkey or Redis OSS key does not exist.
+ If the path is restricted syntax:
  + Returns an integer, memory size, and the JSON value in bytes.
  + Returns null if the Valkey or Redis OSS key does not exist.

FIELDS
+ If the path is enhanced syntax:
  + Returns an array of integers that represent the number of fields of JSON value at each path.
  + Returns an empty array if the Valkey or Redis OSS key does not exist.
+ If the path is restricted syntax:
  + Returns an integer, number of fields of the JSON value.
  + Returns null if the Valkey or Redis OSS key does not exist.

HELP – Returns an array of help messages.

**Examples**

Enhanced path syntax:

```
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
```

Restricted path syntax:

```
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>

Deletes the JSON values at the path in a document key. If the path is the root, it is equivalent to deleting the key from Valkey or Redis OSS.

Syntax

```
JSON.DEL <key> [path]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**
+ Number of elements deleted.
+ 0 if the Valkey or Redis OSS key does not exist.
+ 0 if the JSON path is invalid or does not exist.

**Examples**

 Enhanced path syntax:

```
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\":[]}"
```

 Restricted path syntax:

```
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>

An alias of [JSON.DEL](json-del.md).

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

Returns the serialized JSON at one or multiple paths.

Syntax

```
JSON.GET <key>
[INDENT indentation-string]
[NEWLINE newline-string]
[SPACE space-string]
[NOESCAPE]
[path ...]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ INDENT/NEWLINE/SPACE (optional) – Controls the format of the returned JSON string, that is, "pretty print". The default value of each one is an empty string. They can be overridden in any combination. They can be specified in any order.
+ NOESCAPE - Optional, allowed to be present for legacy compatibility and has no other effect.
+ path (optional) – Zero or more JSON paths, defaults to the root if none is given. The path arguments must be placed at the end.

**Return**

Enhanced path syntax:

 If one path is given:
+ Returns serialized string of an array of values.
+ If no value is selected, the command returns an empty array.

 If multiple paths are given:
+ Returns a stringified JSON object, in which each path is a key.
+ If there are mixed enhanced and restricted path syntax, the result conforms to the enhanced syntax.
+ If a path does not exist, its corresponding value is an empty array.

**Examples**

 Enhanced path syntax:

```
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]"
```

 Restricted path syntax:

```
 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>

Gets serialized JSONs at the path from multiple document keys. It returns null for a nonexistent key or JSON path.

**Syntax**

```
JSON.MGET <key> [key ...] <path>
```
+ key (required) – One or more Valkey or Redis OSS keys of document type.
+ path (required) – A JSON path.

**Return**
+ Array of bulk strings. The size of the array is equal to the number of keys in the command. Each element of the array is populated with either (a) the serialized JSON as located by the path or (b) null if the key does not exist, the path does not exist in the document, or the path is invalid (syntax error).
+ If any of the specified keys exists and is not a JSON key, the command returns `WRONGTYPE` error.

**Examples**

Enhanced path syntax:

```
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\"]"
```

 Restricted path syntax:

```
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.MSET
<a name="json-mset"></a>

Supported for Valkey version 8.1 and above.

Set JSON values for multiple keys. The operation is atomic. Either all values are set or none is set.

**Syntax**

```
JSON.MSET key path json [ key path json ... ]
```
+ If the path calls for an object member:
  + If the parent element does not exist, the command will return NONEXISTENT error.
  + If the parent element exists but is not an object, the command will return ERROR.
  + If the parent element exists and is an object:
    + If the member does not exist, a new member will be appended to the parent object if and only if the parent object is the last child in the path. Otherwise, the command will return NONEXISTENT error.
    + If the member exists, its value will be replaced by the JSON value.
+ If the path calls for an array index:
  + If the parent element does not exist, the command will return a NONEXISTENT error.
  + If the parent element exists but is not an array, the command will return ERROR.
  + If the parent element exists but the index is out of bounds, the command will return OUTOFBOUNDARIES error.
  + If the parent element exists and the index is valid, the element will be replaced by the new JSON value.
+ If the path calls for an object or array, the value (object or array) will be replaced by the new JSON value.

**Return**
+ Simple string reply: 'OK' if the operation was successful.
+ Simple error reply: If the operation failed.

**Examples**

Enhanced path syntax:

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

Restricted path syntax:

```
127.0.0.1:6379> JSON.MSET k1 . '{"name": "John","address": {"street": "123 Main St","city": "Springfield"},"phones": ["555-1234","555-5678"]}'
OK
127.0.0.1:6379> JSON.MSET k1 .address.street '"21 2nd Street"' k1 .address.city '"New York"'
OK
127.0.0.1:6379> JSON.GET k1 .address.street
"\"21 2nd Street\""
127.0.0.1:6379> JSON.GET k1 .address.city
"\"New York\""
```

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

Increments the number values at the path by a given number.

Syntax

```
JSON.NUMINCRBY <key> <path> <number>
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path.
+ number (required) – A number.

**Return**

If the path is enhanced syntax:
+ Array of bulk strings that represents the resulting value at each path.
+ If a value is not a number, its corresponding return value is null.
+ `WRONGTYPE` error if the number cannot be parsed.
+ `OVERFLOW` error if the result is out of the range of 64-bit IEEE double.
+ `NONEXISTENT` if the document key does not exist.

If the path is restricted syntax:
+ Bulk string that represents the resulting value.
+ If multiple values are selected, the command returns the result of the last updated value.
+ `WRONGTYPE` error if the value at the path is not a number.
+ `WRONGTYPE` error if the number cannot be parsed.
+ `OVERFLOW` error if the result is out of the range of 64-bit IEEE double.
+ `NONEXISTENT` if the document key does not exist.

**Examples**

 Enhanced path syntax:

```
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}}"
```

 Restricted path syntax:

```
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>

Multiplies the number values at the path by a given number.

Syntax

```
JSON.NUMMULTBY <key> <path> <number>
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path.
+ number (required) – A number.

**Return**

If the path is enhanced syntax:
+ Array of bulk strings that represent the resulting value at each path.
+ If a value is not a number, its corresponding return value is null.
+ `WRONGTYPE` error if the number cannot be parsed.
+ `OVERFLOW` error if the result is out of the range of a 64-bit IEEE double precision floating point number.
+ `NONEXISTENT` if the document key does not exist.

If the path is restricted syntax:
+ Bulk string that represents the resulting value.
+ If multiple values are selected, the command returns the result of the last updated value.
+ `WRONGTYPE` error if the value at the path is not a number.
+ `WRONGTYPE` error if the number cannot be parsed.
+ `OVERFLOW` error if the result is out of the range of a 64-bit IEEE double.
+ `NONEXISTENT` if the document key does not exist.

**Examples**

 Enhanced path syntax:

```
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]"
```

 Restricted path syntax:

```
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>

Gets the number of keys in the object values at the path.

Syntax

```
JSON.OBJLEN <key> [path]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of integers that represent the object length at each path.
+ If a value is not an object, its corresponding return value is null.
+ Null if the document key does not exist.

If the path is restricted syntax:
+ Integer, number of keys in the object.
+ If multiple objects are selected, the command returns the first object's length.
+ `WRONGTYPE` error if the value at the path is not an object.
+ `NONEXISTENT JSON` error if the path does not exist.
+ Null if the document key does not exist.

**Examples**

 Enhanced path syntax:

```
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)
```

 Restricted path syntax:

```
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>

Gets key names in the object values at the path.

Syntax

```
JSON.OBJKEYS <key> [path]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of array of bulk strings. Each element is an array of keys in a matching object.
+ If a value is not an object, its corresponding return value is empty value.
+ Null if the document key does not exist.

If the path is restricted syntax:
+ Array of bulk strings. Each element is a key name in the object.
+ If multiple objects are selected, the command returns the keys of the first object.
+ `WRONGTYPE` error if the value at the path is not an object.
+ Null if the document key does not exist.

**Examples**

 Enhanced path syntax:

```
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"
```

 Restricted path syntax:

```
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>

Returns the JSON value at the given path in the Valkey or Redis OSS Serialization Protocol (RESP). If the value is container, the response is a RESP array or nested array.
+ JSON null is mapped to the RESP Null Bulk String.
+ JSON Boolean values are mapped to the respective RESP Simple Strings.
+ Integer numbers are mapped to RESP Integers.
+ 64-bit IEEE double floating point numbers are mapped to RESP Bulk Strings.
+ JSON strings are mapped to RESP Bulk Strings.
+ JSON arrays are represented as RESP Arrays, where the first element is the simple string [, followed by the array's elements.
+ JSON objects are represented as RESP Arrays, where the first element is the simple string \$1, followed by key-value pairs, each of which is a RESP bulk string.

Syntax

```
JSON.RESP <key> [path]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of arrays. Each array element represents the RESP form of the value at one path.
+ Empty array if the document key does not exist.

If the path is restricted syntax:
+ Array that represents the RESP form of the value at the path.
+ Null if the document key does not exist.

**Examples**

Enhanced path syntax:

```
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"
```

Restricted path syntax:

```
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>

Sets JSON values at the path.

If the path calls for an object member:
+ If the parent element does not exist, the command returns a NONEXISTENT error.
+ If the parent element exists but is not an object, the command returns ERROR.
+ If the parent element exists and is an object:
  +  If the member does not exist, a new member will be appended to the parent object if and only if the parent object is the last child in the path. Otherwise, the command returns a NONEXISTENT error.
  +  If the member exists, its value will be replaced by the JSON value.

If the path calls for an array index:
+ If the parent element does not exist, the command returns a NONEXISTENT error.
+ If the parent element exists but is not an array, the command returns ERROR.
+ If the parent element exists but the index is out of bounds, the command returns an OUTOFBOUNDARIES error.
+ If the parent element exists and the index is valid, the element will be replaced by the new JSON value.

If the path calls for an object or array, the value (object or array) will be replaced by the new JSON value.

Syntax

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

[NX \$1 XX] Where you can have 0 or 1 of [NX \$1 XX] identifiers.
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (required) – A JSON path. For a new key, the JSON path must be the root ".".
+ NX (optional) – If the path is the root, set the value only if the key does not exist. That is, insert a new document. If the path is not the root, set the value only if the path does not exist. That is, insert a value into the document.
+ XX (optional) – If the path is the root, set the value only if the key exists. That is, replace the existing document. If the path is not the root, set the value only if the path exists. That is, update the existing value.

**Return**
+ Simple String 'OK' on success.
+ Null if the NX or XX condition is not met.

**Examples**

 Enhanced path syntax:

```
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]}"
```

 Restricted path syntax:

```
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>

Appends a string to the JSON strings at the path.

Syntax

```
JSON.STRAPPEND <key> [path] <json_string>
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.
+ json\$1string (required) – The JSON representation of a string. Note that a JSON string must be quoted. For example: '"string example"'.

**Return**

If the path is enhanced syntax:
+ Array of integers that represent the new length of the string at each path.
+ If a value at the path is not a string, its corresponding return value is null.
+ `SYNTAXERR` error if the input json argument is not a valid JSON string.
+ `NONEXISTENT` error if the path does not exist.

If the path is restricted syntax:
+ Integer, the string's new length.
+ If multiple string values are selected, the command returns the new length of the last updated string.
+ `WRONGTYPE` error if the value at the path is not a string.
+ `WRONGTYPE` error if the input json argument is not a valid JSON string.
+ `NONEXISTENT` error if the path does not exist.

**Examples**

 Enhanced path syntax:

```
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)
```

 Restricted path syntax:

```
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>

Gets the lengths of the JSON string values at the path.

Syntax

```
JSON.STRLEN <key> [path] 
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of integers that represents the length of the string value at each path.
+ If a value is not a string, its corresponding return value is null.
+ Null if the document key does not exist.

If the path is restricted syntax:
+ Integer, the string's length.
+ If multiple string values are selected, the command returns the first string's length.
+ `WRONGTYPE` error if the value at the path is not a string.
+ `NONEXISTENT` error if the path does not exist.
+ Null if the document key does not exist.

**Examples**

 Enhanced path syntax:

```
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)
```

 Restricted path syntax:

```
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>

Toggles Boolean values between true and false at the path.

Syntax

```
JSON.TOGGLE <key> [path] 
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of integers (0 - false, 1 - true) that represent the resulting Boolean value at each path.
+ If a value is a not a Boolean value, its corresponding return value is null.
+ `NONEXISTENT` if the document key does not exist.

If the path is restricted syntax:
+ String ("true"/"false") that represents the resulting Boolean value.
+ `NONEXISTENT` if the document key does not exist.
+ `WRONGTYPE` error if the value at the path is not a Boolean value.

**Examples**

 Enhanced path syntax:

```
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)
```

 Restricted path syntax:

```
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>

Reports the type of values at the given path.

Syntax

```
JSON.TYPE <key> [path]
```
+ key (required) – A Valkey or Redis OSS key of JSON document type.
+ path (optional) – A JSON path. Defaults to the root if not provided.

**Return**

If the path is enhanced syntax:
+ Array of strings that represent the type of value at each path. The type is one of \$1"null", "boolean", "string", "number", "integer", "object" and "array"\$1.
+ If a path does not exist, its corresponding return value is null.
+ Empty array if the document key does not exist.

If the path is restricted syntax:
+ String, type of the value
+ Null if the document key does not exist.
+ Null if the JSON path is invalid or does not exist.

**Examples**

Enhanced path syntax:

```
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
```

Restricted path syntax:

```
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
```