# GJSON Path Syntax A GJSON Path is a text string syntax that describes a search pattern for quickly retrieving values from a JSON payload. 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) - [Multi-paths](#multi-paths) - [Literals](#literals) The definitive implementation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson). Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax online. ## Path structure A GJSON Path is intended to be easily expressed as a series of components separated by a `.` character. Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, `!`, and `?`. ## Example Given this JSON ```json { "name": {"first": "Tom", "last": "Anderson"}, "age":37, "children": ["Sara","Alex","Jack"], "fav.movie": "Deer Hunter", "friends": [ {"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"]} ] } ``` The following GJSON Paths evaluate to the accompanying values. ### Basic Often, you'll just want to retrieve values by object name or array index. ```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 A key may contain the special wildcard characters `*` and `?`. The `*` will match on any zero+ characters, and `?` matches on any one character. ```go child*.2 "Jack" c?ildren.0 "Sara" ``` ### Escape character Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`. ```go fav\.movie "Deer Hunter" ``` You'll also need to make sure that the `\` character is correctly escaped when hard-coding a path in your source code. ```go // Go val := gjson.Get(json, "fav\\.movie") // must escape the slash val := gjson.Get(json, `fav\.movie`) // no need to escape the slash ``` ```rust // Rust let val = gjson::get(json, "fav\\.movie") // must escape the slash let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash ``` ### 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 You can also query an array for the first match by using `#(...)`, or find all matches with `#(...)#`. Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators, and the simple pattern matching `%` (like) and `!%` (not like) operators. ```go 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" ``` To query for a non-object value in an array, you can forgo the string to the right of the operator. ```go children.#(!%"*a*") "Alex" children.#(%"*a*")# ["Sara","Jack"] ``` Nested queries are allowed. ```go friends.#(nets.#(=="fb"))#.first >> ["Dale","Roger"] ``` *Please note that before v1.3.0, queries used the `#[...]` brackets. This was changed in v1.3.0 as to avoid confusion with the new [multi-paths](#multi-paths) syntax. For backwards compatibility, `#[...]` will continue to work until the next major release.* The `~` (tilde) operator will convert a value to a boolean before comparison. 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 ``` For example, using the following JSON: ```json { "vals": [ { "a": 1, "b": "data" }, { "a": 2, "b": true }, { "a": 3, "b": false }, { "a": 4, "b": "0" }, { "a": 5, "b": 0 }, { "a": 6, "b": "1" }, { "a": 7, "b": 1 }, { "a": 8, "b": "true" }, { "a": 9, "b": false }, { "a": 10, "b": null }, { "a": 11 } ] } ``` To query for all true-ish or false-ish values: ``` vals.#(b==~true)#.a >> [2,6,7,8] vals.#(b==~false)#.a >> [3,4,5,9,10,11] ``` The last value which was non-existent is treated as `false` 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] ``` ### Dot vs. Pipe The `.` is standard separator, but it's also possible to use a `|`. Usually, they both end up returning the same results. The cases where`|` differs from `.` is when it's used after the `#` for [Arrays](#arrays) and [Queries](#queries). 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 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 friends.#(last="Murphy")#.0 [] friends.#(last="Murphy")#|0 {"first": "Dale", "last": "Murphy", "age": 44} friends.#(last="Murphy")#.# [] friends.#(last="Murphy")#|# 2 ``` Let's break down a few of these. The path `friends.#(last="Murphy")#` all by itself results in ```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"] ``` 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 impossible to process 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" ``` These are currently the following built-in modifiers: - `@reverse`: Reverse an array or the members of an object. - `@ugly`: Remove all whitespace from JSON. - `@pretty`: Make the JSON more human-readable. - `@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. - `@keys`: Returns an array of keys for an object. - `@values`: Returns an array of values for an object. - `@tostr`: Converts JSON to a string. Wraps a JSON string. - `@fromstr`: Converts a string from JSON. Unwraps a JSON string. - `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db). - `@dig`: Search for a value without providing its entire path. See [e8e87f2](https://github.com/tidwall/gjson/commit/e8e87f2a00dc41f3aba5631094e21f59a8cf8cbf). #### 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 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"} } ``` *The full list of `@pretty` options are `sortKeys`, `indent`, `prefix`, and `width`. Please see [Pretty Options](https://github.com/tidwall/pretty#customized-output) for more information.* #### Custom modifiers You can also add custom modifiers. 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"] ``` *Note: Custom modifiers are not yet available in the Rust version* ### Multi-paths Starting with v1.3.0, GJSON added the ability to join multiple paths together to form new documents. Wrapping comma-separated paths between `[...]` or `{...}` will result in a new array or object, respectively. For example, using the given multi-path: ``` {name.first,age,"the_murphys":friends.#(last="Murphy")#.first} ``` Here we selected the first name, age, and the first name for friends with the last name `Murphy`. 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 actual field will be used, in this case `first`. If a name cannot be determined, then `_` is used. This results in ```json {"first":"Tom","age":37,"the_murphys":["Dale","Jane"]} ``` ### Literals Starting with v1.12.0, GJSON added support of JSON literals, which provides a way for constructing static blocks of JSON. This can be particularly useful when constructing a new JSON document using [multi-paths](#multi-paths). A JSON literal begins with the '!' declaration character. For example, using the given multi-path: ``` {name.first,age,"company":!"Happysoft","employed":!true} ``` Here we selected the first name and age. Then add two new fields, `company` and `employed`. This results in ```json {"first":"Tom","age":37,"company":"Happysoft","employed":true} ``` *See issue [#249](https://github.com/tidwall/gjson/issues/249) for additional context on JSON Literals.*