

# Getting started with JSON


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

In addition to leveraging Valkey or Redis OSS APIs 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, which 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 creating a cluster with a supported engine version, the JSON data type and associated commands are automatically available. This is API-compatible and RDB-compatible with version 2 of the RedisJSON module, so you can easily migrate existing JSON-based Valkey or Redis OSS applications into MemoryDB. For more information on the supported commands, see [Supported commands](json-list-commands.md).

JSON-related metric `JsonBasedCmds` is incorporated into CloudWatch to monitor the usage of this datatype. For more information, see [Metrics for MemoryDB](https://docs.aws.amazon.com/memorydb/latest/devguide/metrics.memorydb.html).

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

**Topics**
+ [

# JSON Datatype overview
](json-document-overview.md)
+ [

# Supported commands
](json-list-commands.md)

# JSON Datatype overview


MemoryDB supports a number of Valkey and Redis OSS commands for working with the JSON datatype. Following is an overview of the JSON datatype and a detailed list of commands that are supported.

## Terminology



****  

| 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


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


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


JSON documents are stored internally in a format optimized for rapid access and modification. This format typically results in consuming somewhat more memory than does the equivalent serialized representation of the same document. The consumption of memory by a single JSON document is limited to 64MB, which is the size of the in-memory data structure, not the JSON string. The amount of memory consumed by a JSON document can be inspected by using the `JSON.DEBUG MEMORY` command.

## JSON ACLs

+ JSON datatype is fully integrated into the Valkey and Redis OSS [Access Control Lists (ACL)](https://valkey.io/topics/acl/) capability. 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 ACL categories that are updated to include the new JSON commands: @read, @write, @fast, @slow and @admin. The table below 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


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


Most commands require a Valkey or Redis OSS key name as the first argument. Some commands also have a path argument. The path argument defaults to the root if it is optional and not provided.

 Notation:
+ Required arguments are enclosed in angle brackets, e.g. <key>
+ Optional arguments are enclosed in square brackets, e.g. [path]
+ Additional optional arguments are indicated by ..., e.g. [json ...]

## Path syntax


JSON for Valkey and Redis OSS supports two kinds of path syntaxes:
+ **Enhanced syntax** – Follows the JSONPath syntax described by [Goessner](https://goessner.net/articles/JsonPath/), as shown in the table below. 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 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 referring 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 below 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 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 whitespaces) | 
|  '\$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 whitespaces) | 
|  \$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 whitespaces) | 
|  '\$1.store.book[?(@.["category"] == "fiction")]' | all books in the fiction category | 
|  '\$1.store.book[?(@.["category"] \$1= "fiction")]' | all books in non-fiction categories | 

More 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


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


****  

| Prefix | Description | 
| --- | --- | 
|  ERR | a general error | 
|  LIMIT | size limit exceeded error. e.g., the document size limit or nesting depth limit 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


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 the Valkey or Redis OSS engine | 

To query core metrics, run the command:

```
info json_core_metrics
```

## How MemoryDB interacts with JSON


The following illustrates how MemoryDB interacts with the JSON datatype.

### Operator precedence


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 will be executed first. 

### Maximum path nesting limit behavior


MemoryDB's maximum path nesting limit is 128. So a value like `$.a.b.c.d...` can only reach 128 levels. 

### Handling numeric values


JSON does not have separate data types for integers and floating point numbers. They are all called numbers.

When a JSON number is received, it is stored in one of two formats. If the number fits into a 64-bit signed integer, then it is converted to that format; otherwise, it is stored as a string. Arithmetic operations on two JSON numbers (e.g. JSON.NUMINCRBY and JSON.NUMMULTBY) attempt to preserve as much precision as possible. If the two operands and the resulting value fit into a 64-bit signed integer, then integer arithmetic is performed. Otherwise, the input operands are converted into 64-bit IEEE double-precision floating point numbers, the arithmetic operation is performed, and the result is converted back into a string.

Arithmetic commands `NUMINCRBY` and `NUMMULTBY`:
+ If both numbers are integers, and the result is out of the range of int64, it will automatically become a double precision floating point number.
+ If at least one of the numbers is a floating point, the result will be a double precision floating point number.
+ If the result exceeds the range of double, the command will return an `OVERFLOW` error.

**Note**  
Prior to Redis OSS engine version 6.2.6.R2 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.  
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 commands](json-list-commands.md).

### Strict syntax evaluation


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 commands


The following JSON commands are supported:

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


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

Syntax

```
JSON.ARRAPPEND <key> <path> <json> [json ...]
```
+ key (required) – key of JSON document type
+ path (required) – a JSON path
+ json (required) – JSON value to be appended to the array

**Return**

If the path is enhanced syntax:
+ Array of integers, representing the new length of the array at each path.
+ If a value is not an array, its corresponding return value is null.
+ `SYNTAXERR` error if one of the input json arguments is not a valid JSON string.
+ `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 last 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


Search 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) – key of JSON document type
+ path (required) – a JSON path
+ json-scalar (required) – scalar value to search for; JSON scalar refers to values that are not objects or arrays. i.e., String, number, boolean and null are scalar values.
+ start (optional) – start index, inclusive. Defaults to 0 if not provided.
+ end (optional) – end index, exclusive. Defaults to 0 if not provided, which means 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


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

Syntax

```
JSON.ARRINSERT <key> <path> <index> <json> [json ...]
```
+ key (required) – key of JSON document type
+ path (required) – a JSON path
+ index (required) – array index before which values are inserted.
+ json (required) – JSON value to be appended to the array

**Return**

If the path is enhanced syntax:
+ Array of integers, representing 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


Get length of the array values at the path.

Syntax

```
JSON.ARRLEN <key> [path] 
```
+ key (required) – 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, representing 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:
+ Array of bulk strings. Each element is a key name in the object.
+ 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.
+ `WRONGTYPE` 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\"]]'
(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)
```

 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 $[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


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

Syntax

```
JSON.ARRPOP <key> [path [index]]
```
+ key (required) – key of JSON document type
+ path (optional) – a JSON path. Defaults to the root if not provided
+ index (optional) – 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, representing 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, representing 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


Trim arrays at the path so that it becomes 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.ARRINSERT <key> <path> <start> <end>
```
+ key (required) – key of JSON document type
+ path (required) – a JSON path
+ start (required) – start index, inclusive.
+ end (required) – end index, inclusive.

**Return**

If the path is enhanced syntax:
+ Array of integers, representing 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


Clear the arrays or an objects at the path.

Syntax

```
JSON.CLEAR <key> [path]
```
+ key (required) – 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 0 container cleared.
**Note**  
Prior to Redis OSS version 6.2.6.R2, clearing an empty array or object accounts for 1 container cleared.
+ Clearing a non-container value returns 0.
+ If no array or object value is located by the path, the command 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) 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


Report information. Supported subcommands are:
+ MEMORY <key> [path] – report memory usage in bytes of a JSON value. Path defaults to the root if not provided.
+ DEPTH <key> [path] – Reports the maximum path depth of the JSON document.
**Note**  
This subcommand is only available using Valkey 7.2 or later, or Redis OSS engine version 6.2.6.R2 or later.
+ FIELDS <key> [path] – report 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 – print 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, representing memory size (in bytes) of JSON value at each path.
  + returns an empty array if the key does not exist.
+ If the path is restricted syntax:
  + returns an integer, memory size the JSON value in bytes.
  + returns null if the key does not exist.

DEPTH
+ Returns an integer that represents the maximum path depth of the JSON document.
+ Returns null if the key does not exist.

FIELDS
+ If the path is enhanced syntax:
  + returns an array of integers, representing number of fields of JSON value at each path.
  + returns an empty array if the key does not exist.
+ If the path is restricted syntax:
  + returns an integer, number of fields of the JSON value.
  + returns null if the 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


Delete 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) – 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 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


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

# JSON.GET


Return 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) – key of JSON document type
+ INDENT/NEWLINE/SPACE (optional) – controls the format of the returned JSON string, i.e., "pretty print". The default value of each one is empty string. They can be overidden 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:
+ Return serialized string of an array of values.
+ If no value is selected, the command returns an empty array.

 If multiple paths are given:
+ Return 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


Get serialized JSONs at the path from multiple document keys. Return null for non-existent key or JSON path.

Syntax

```
JSON.MGET <key> [key ...] <path>
```
+ key (required) – One or more 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 or 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.NUMINCRBY


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

Syntax

```
JSON.NUMINCRBY <key> <path> <number>
```
+ key (required) – 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 representing 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 representing 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


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

Syntax

```
JSON.NUMMULTBY <key> <path> <number>
```
+ key (required) – 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 representing 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 representing 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.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


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

Syntax

```
JSON.OBJLEN <key> [path]
```
+ key (required) – 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, representing 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.
+ `WRONGTYPE` 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


Get key names in the object values at the path.

Syntax

```
JSON.OBJKEYS <key> [path]
```
+ key (required) – 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.
+ `WRONGTYPE` 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.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


Return the JSON value at the given path in the Valkey or Redis OSS Serialization Protocol (RESP). If the value is container, the response is 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) – 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, representing 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


Set JSON values at the path.

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.

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) – key of JSON document type
+ path (required) – 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, i.e., insert a new document. If the path is not the root, set the value only if the path does not exist, i.e., insert a value into the document.
+ XX (optional) – If the path is the root, set the value only if the key exists, i.e., replace the existing document. If the path is not the root, set the value only if the path exists, i.e., 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


Append a string to the JSON strings at the path.

Syntax

```
JSON.STRAPPEND <key> [path] <json_string>
```
+ key (required) – key of JSON document type
+ path (optional) – a JSON path. Defaults to the root if not provided
+ json\$1string (required) – JSON representation of a string. Note that a JSON string must be quoted, i.e., '"foo"'.

**Return**

If the path is enhanced syntax:
+ Array of integers, representing 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


Get lengths of the JSON string values at the path.

Syntax

```
JSON.STRLEN <key> [path] 
```
+ key (required) – 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, representing the length of 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


Toggle boolean values between true and false at the path.

Syntax

```
JSON.TOGGLE <key> [path] 
```
+ key (required) – 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) representing the resulting boolean value at each path.
+ If a value is a not boolean, its corresponding return value is null.
+ `NONEXISTENT` if the document key does not exist.

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

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


Report type of the values at the given path.

Syntax

```
JSON.TYPE <key> [path]
```
+ key (required) – 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, representing type of the 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
```