mirror of https://github.com/tidwall/gjson.git
Create PATH-SYNTAX.md
This commit is contained in:
parent
ebf0b3fb77
commit
f73dd9bfd8
|
@ -0,0 +1,227 @@
|
|||
# GJSON Path Syntax
|
||||
|
||||
A GJSON Path is a text string syntax that describes a search pattern for quickly retreiving 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)
|
||||
|
||||
The definitive implemenation is [github.com/tidwall/gjson](https://github.com/tidwall/gjson).
|
||||
|
||||
|
||||
## Path structure
|
||||
|
||||
A GJSON Path is intended to be easily expressed as a series of components seperated 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},
|
||||
{"first": "Roger", "last": "Craig", "age": 68},
|
||||
{"first": "Jane", "last": "Murphy", "age": 47}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The following GJSON Paths evaluate to the accompanying values.
|
||||
|
||||
### Basic
|
||||
|
||||
In many cases you'll just want to retreive 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"
|
||||
```
|
||||
|
||||
|
||||
### 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"]
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Dot vs Pipe
|
||||
|
||||
The `.` is standard separator, but it's also possible to use a `|`.
|
||||
In most cases 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 <non-existent>
|
||||
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 not possible 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"
|
||||
```
|
||||
|
||||
There are currently three 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.
|
||||
|
||||
#### 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"}
|
||||
}
|
||||
```
|
||||
|
||||
*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"]
|
||||
```
|
||||
|
Loading…
Reference in New Issue