2019-06-29 03:11:56 +03:00
# GJSON Path Syntax
2024-04-15 06:43:24 +03:00
A GJSON Path is a text string syntax that describes a search pattern for quickly retrieving values from a JSON payload.
2019-06-29 03:11:56 +03:00
This document is designed to explain the structure of a GJSON Path through examples.
- [Path structure ](#path-structure )
- [Basic ](#basic )
- [Wildcards ](#wildcards )
- [Escape Character ](#escape-character )
- [Arrays ](#arrays )
- [Queries ](#queries )
- [Dot vs Pipe ](#dot-vs-pipe )
- [Modifiers ](#modifiers )
2019-11-01 15:15:58 +03:00
- [Multipaths ](#multipaths )
2021-11-30 20:18:36 +03:00
- [Literals ](#literals )
2019-06-29 03:11:56 +03:00
2024-04-23 14:35:22 +03:00
The definitive implementation is [github.com/tidwall/gjson ](https://github.com/tidwall/gjson ).
2019-07-11 01:00:07 +03:00
Use the [GJSON Playground ](https://gjson.dev ) to experiment with the syntax online.
2019-06-29 03:11:56 +03:00
## Path structure
2024-04-23 14:35:22 +03:00
A GJSON Path is intended to be easily expressed as a series of components separated by a `.` character.
2019-06-29 03:11:56 +03:00
2021-12-10 19:23:12 +03:00
Along with `.` character, there are a few more that have special meaning, including `|` , `#` , `@` , `\` , `*` , `!` , and `?` .
2019-06-29 03:11:56 +03:00
## Example
Given this JSON
```json
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
2019-07-12 16:46:38 +03:00
{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
2019-06-29 03:11:56 +03:00
]
}
```
The following GJSON Paths evaluate to the accompanying values.
2024-04-23 14:35:22 +03:00
### Basic
2019-06-29 03:11:56 +03:00
2024-04-15 06:43:24 +03:00
In many cases you'll just want to retrieve values by object name or array index.
2019-06-29 03:11:56 +03:00
```go
name.last "Anderson"
name.first "Tom"
age 37
children ["Sara","Alex","Jack"]
children.0 "Sara"
children.1 "Alex"
friends.1 {"first": "Roger", "last": "Craig", "age": 68}
friends.1.first "Roger"
```
### Wildcards
2024-04-23 14:35:22 +03:00
A key may contain the special wildcard characters `*` and `?` .
2019-06-29 03:11:56 +03:00
The `*` will match on any zero+ characters, and `?` matches on any one character.
```go
child*.2 "Jack"
c?ildren.0 "Sara"
```
### Escape character
2024-04-23 14:35:22 +03:00
Special purpose characters, such as `.` , `*` , and `?` can be escaped with `\` .
2019-06-29 03:11:56 +03:00
```go
2020-02-22 20:55:31 +03:00
fav\.movie "Deer Hunter"
```
2021-12-08 19:42:11 +03:00
You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in your source code.
2020-02-22 20:55:31 +03:00
```go
2021-03-27 22:05:13 +03:00
// Go
val := gjson.Get(json, "fav\\.movie") // must escape the slash
2024-04-23 14:35:22 +03:00
val := gjson.Get(json, `fav\.movie` ) // no need to escape the slash
2021-03-27 22:05:13 +03:00
```
2020-02-22 20:55:31 +03:00
2021-03-27 22:05:13 +03:00
```rust
// Rust
let val = gjson::get(json, "fav\\.movie") // must escape the slash
2024-04-23 14:35:22 +03:00
let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash
2019-06-29 03:11:56 +03:00
```
2021-03-27 22:05:13 +03:00
2019-06-29 03:11:56 +03:00
### Arrays
The `#` character allows for digging into JSON Arrays.
To get the length of an array you'll just use the `#` all by itself.
```go
friends.# 3
friends.#.age [44,68,47]
```
### Queries
2024-04-23 14:35:22 +03:00
You can also query an array for the first match by using `#(...)` , or find all matches with `#(...)#` .
Queries support the `==` , `!=` , `<` , `<=` , `>` , `>=` comparison operators,
2019-06-29 03:11:56 +03:00
and the simple pattern matching `%` (like) and `!%` (not like) operators.
```go
2019-06-30 22:59:56 +03:00
friends.#(last=="Murphy").first "Dale"
friends.#(last=="Murphy")#.first ["Dale","Jane"]
friends.#(age>45)#.last ["Craig","Murphy"]
friends.#(first%"D*").last "Murphy"
friends.#(first!%"D*").last "Craig"
2019-06-29 03:11:56 +03:00
```
To query for a non-object value in an array, you can forgo the string to the right of the operator.
2019-06-30 22:59:56 +03:00
2019-06-29 03:11:56 +03:00
```go
2019-06-30 22:59:56 +03:00
children.#(!%"*a*") "Alex"
children.#(%"*a*")# ["Sara","Jack"]
2019-06-29 03:11:56 +03:00
```
2019-07-12 16:46:38 +03:00
Nested queries are allowed.
```go
friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"]
```
2019-06-30 22:59:56 +03:00
*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
2024-04-23 14:35:22 +03:00
changed in v1.3.0 as to avoid confusion with the new [multipath ](#multipaths )
2019-06-30 22:59:56 +03:00
syntax. For backwards compatibility, `#[...]` will continue to work until the
next major release.*
2019-06-29 03:11:56 +03:00
2021-05-14 18:58:36 +03:00
The `~` (tilde) operator will convert a value to a boolean before comparison.
2023-07-27 16:23:49 +03:00
Supported tilde comparison type are:
```
~true Converts true-ish values to true
~false Converts false-ish and non-existent values to true
~null Converts null and non-existent values to true
~* Converts any existing value to true
```
2021-05-14 18:58:36 +03:00
For example, using the following JSON:
```json
{
"vals": [
2023-07-27 16:23:49 +03:00
{ "a": 1, "b": "data" },
2021-05-14 18:58:36 +03:00
{ "a": 2, "b": true },
{ "a": 3, "b": false },
{ "a": 4, "b": "0" },
{ "a": 5, "b": 0 },
{ "a": 6, "b": "1" },
2021-05-14 19:02:12 +03:00
{ "a": 7, "b": 1 },
2021-05-14 18:58:36 +03:00
{ "a": 8, "b": "true" },
2021-05-14 19:02:12 +03:00
{ "a": 9, "b": false },
{ "a": 10, "b": null },
2021-05-14 18:58:36 +03:00
{ "a": 11 }
]
}
```
2023-07-27 16:23:49 +03:00
To query for all true-ish or false-ish values:
2021-05-14 18:58:36 +03:00
```
2023-07-27 16:23:49 +03:00
vals.#(b==~true)#.a >> [2,6,7,8]
2021-05-14 19:08:32 +03:00
vals.#(b==~false)#.a >> [3,4,5,9,10,11]
2021-05-14 18:58:36 +03:00
```
The last value which was non-existent is treated as `false`
2023-07-27 16:23:49 +03:00
To query for null and explicit value existence:
```
vals.#(b==~null)#.a >> [10,11]
vals.#(b==~*)#.a >> [1,2,3,4,5,6,7,8,9,10]
vals.#(b!=~*)#.a >> [11]
```
2019-06-29 03:11:56 +03:00
### Dot vs Pipe
2024-04-23 14:35:22 +03:00
The `.` is standard separator, but it's also possible to use a `|` .
2019-06-29 03:11:56 +03:00
In most cases they both end up returning the same results.
2024-04-23 14:35:22 +03:00
The cases where`|` differs from `.` is when it's used after the `#` for [Arrays ](#arrays ) and [Queries ](#queries ).
2019-06-29 03:11:56 +03:00
Here are some examples
```go
friends.0.first "Dale"
friends|0.first "Dale"
friends.0|first "Dale"
friends|0|first "Dale"
friends|# 3
friends.# 3
2019-06-30 22:59:56 +03:00
friends.#(last="Murphy")# [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
friends.#(last="Murphy")#.first ["Dale","Jane"]
friends.#(last="Murphy")#|first < non-existent >
friends.#(last="Murphy")#.0 []
friends.#(last="Murphy")#|0 {"first": "Dale", "last": "Murphy", "age": 44}
friends.#(last="Murphy")#.# []
friends.#(last="Murphy")#|# 2
2019-06-29 03:11:56 +03:00
```
Let's break down a few of these.
2019-06-30 22:59:56 +03:00
The path `friends.#(last="Murphy")#` all by itself results in
2019-06-29 03:11:56 +03:00
```json
[{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
```
The `.first` suffix will process the `first` path on each array element *before* returning the results. Which becomes
```json
["Dale","Jane"]
```
2024-04-23 14:35:22 +03:00
But the `|first` suffix actually processes the `first` path *after* the previous result.
Since the previous result is an array, not an object, it's not possible to process
2019-06-29 03:11:56 +03:00
because `first` does not exist.
Yet, `|0` suffix returns
```json
{"first": "Dale", "last": "Murphy", "age": 44}
```
Because `0` is the first index of the previous result.
### Modifiers
A modifier is a path component that performs custom processing on the JSON.
For example, using the built-in `@reverse` modifier on the above JSON payload will reverse the `children` array:
```go
children.@reverse ["Jack","Alex","Sara"]
children.@reverse.0 "Jack"
```
Added new modifiers
`@flatten` Flattens an array with child arrays.
[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]
The {"deep":true} arg can be provide for deep flattening.
[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]
The original json is returned when the json is not an array.
`@join` Joins multiple objects into a single object.
[{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}
The arg can be "true" to specify that duplicate keys should be preserved.
[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}
Without preserved keys:
[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}
The original json is returned when the json is not an object.
`@valid` Ensures that the json is valid before moving on. An
empty string is returned when the json is not valid, otherwise
it returns the original json.
2020-02-10 21:13:30 +03:00
There are currently the following built-in modifiers:
2019-06-29 03:11:56 +03:00
- `@reverse` : Reverse an array or the members of an object.
- `@ugly` : Remove all whitespace from JSON.
- `@pretty` : Make the JSON more human readable.
Added new modifiers
`@flatten` Flattens an array with child arrays.
[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]
The {"deep":true} arg can be provide for deep flattening.
[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]
The original json is returned when the json is not an array.
`@join` Joins multiple objects into a single object.
[{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}
The arg can be "true" to specify that duplicate keys should be preserved.
[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}
Without preserved keys:
[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}
The original json is returned when the json is not an object.
`@valid` Ensures that the json is valid before moving on. An
empty string is returned when the json is not valid, otherwise
it returns the original json.
2020-02-10 21:13:30 +03:00
- `@this` : Returns the current element. It can be used to retrieve the root element.
- `@valid` : Ensure the json document is valid.
- `@flatten` : Flattens an array.
- `@join` : Joins multiple objects into a single object.
2021-10-21 02:31:29 +03:00
- `@keys` : Returns an array of keys for an object.
- `@values` : Returns an array of values for an object.
2022-01-13 19:15:39 +03:00
- `@tostr` : Converts json to a string. Wraps a json string.
- `@fromstr` : Converts a string from json. Unwraps a json string.
2022-02-02 14:59:12 +03:00
- `@group` : Groups arrays of objects. See [e4fc67c ](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db ).
2023-08-10 01:08:32 +03:00
- `@dig` : Search for a value without providing its entire path. See [e8e87f2 ](https://github.com/tidwall/gjson/commit/e8e87f2a00dc41f3aba5631094e21f59a8cf8cbf ).
2019-06-29 03:11:56 +03:00
#### Modifier arguments
A modifier may accept an optional argument. The argument can be a valid JSON payload or just characters.
For example, the `@pretty` modifier takes a json object as its argument.
```
@pretty: {"sortKeys":true}
```
Which makes the json pretty and orders all of its keys.
```json
{
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"age": 44, "first": "Dale", "last": "Murphy"},
{"age": 68, "first": "Roger", "last": "Craig"},
{"age": 47, "first": "Jane", "last": "Murphy"}
],
"name": {"first": "Tom", "last": "Anderson"}
}
```
2024-04-23 14:35:22 +03:00
*The full list of `@pretty` options are `sortKeys` , `indent` , `prefix` , and `width` .
2019-06-29 03:11:56 +03:00
Please see [Pretty Options ](https://github.com/tidwall/pretty#customized-output ) for more information.*
#### Custom modifiers
2024-04-23 14:35:22 +03:00
You can also add custom modifiers.
2019-06-29 03:11:56 +03:00
For example, here we create a modifier which makes the entire JSON payload upper or lower case.
```go
gjson.AddModifier("case", func(json, arg string) string {
if arg == "upper" {
return strings.ToUpper(json)
}
if arg == "lower" {
return strings.ToLower(json)
}
return json
})
"children.@case:upper" ["SARA","ALEX","JACK"]
"children.@case:lower.@reverse" ["jack","alex","sara"]
```
2021-03-27 22:06:30 +03:00
*Note: Custom modifiers are not yet available in the Rust version*
2019-11-01 15:15:58 +03:00
### Multipaths
2019-06-30 22:59:56 +03:00
Starting with v1.3.0, GJSON added the ability to join multiple paths together
2021-07-07 04:52:23 +03:00
to form new documents. Wrapping comma-separated paths between `[...]` or
`{...}` will result in a new array or object, respectively.
2019-06-30 22:59:56 +03:00
2021-11-30 20:18:36 +03:00
For example, using the given multipath:
2019-06-30 22:59:56 +03:00
```
{name.first,age,"the_murphys":friends.#(last="Murphy")#.first}
```
2024-04-23 14:35:22 +03:00
Here we selected the first name, age, and the first name for friends with the
2019-06-30 22:59:56 +03:00
last name "Murphy".
2024-04-23 14:35:22 +03:00
You'll notice that an optional key can be provided, in this case
"the_murphys", to force assign a key to a value. Otherwise, the name of the
2019-06-30 22:59:56 +03:00
actual field will be used, in this case "first". If a name cannot be
determined, then "_" is used.
This results in
2021-11-30 20:18:36 +03:00
```json
2019-06-30 22:59:56 +03:00
{"first":"Tom","age":37,"the_murphys":["Dale","Jane"]}
```
2021-11-30 20:18:36 +03:00
### Literals
2024-04-23 14:35:22 +03:00
Starting with v1.12.0, GJSON added support of json literals, which provides a way for constructing static blocks of json. This is can be particularly useful when constructing a new json document using [multipaths ](#multipaths ).
2021-11-30 20:18:36 +03:00
2024-04-23 14:35:22 +03:00
A json literal begins with the '!' declaration character.
2021-11-30 20:18:36 +03:00
For example, using the given multipath:
```
{name.first,age,"company":!"Happysoft","employed":!true}
```
Here we selected the first name and age. Then add two new fields, "company" and "employed".
2024-04-23 14:35:22 +03:00
This results in
2021-11-30 20:18:36 +03:00
```json
{"first":"Tom","age":37,"company":"Happysoft","employed":true}
```
2019-06-30 22:59:56 +03:00
2021-11-30 20:18:36 +03:00
*See issue [#249 ](https://github.com/tidwall/gjson/issues/249 ) for additional context on JSON Literals.*