Add multipath syntax

This commit is contained in:
tidwall 2019-06-30 12:59:56 -07:00
parent d7c940e593
commit 4d138e058b
2 changed files with 65 additions and 26 deletions

View File

@ -90,17 +90,25 @@ The dot and wildcard characters can be escaped with '\\'.
"friends.1.last" >> "Craig" "friends.1.last" >> "Craig"
``` ```
You can also query an array for the first match by using `#[...]`, or find all matches with `#[...]#`. You can also query an array for the first match by using `#(...)`, or find all
Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators and the simple pattern matching `%` (like) and `!%` (not like) operators. matches with `#(...)#`. Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=`
comparison operators and the simple pattern matching `%` (like) and `!%`
(not like) operators.
``` ```
friends.#[last=="Murphy"].first >> "Dale" friends.#(last=="Murphy").first >> "Dale"
friends.#[last=="Murphy"]#.first >> ["Dale","Jane"] friends.#(last=="Murphy")#.first >> ["Dale","Jane"]
friends.#[age>45]#.last >> ["Craig","Murphy"] friends.#(age>45)#.last >> ["Craig","Murphy"]
friends.#[first%"D*"].last >> "Murphy" friends.#(first%"D*").last >> "Murphy"
friends.#[first!%"D*"].last >> "Craig" friends.#(first!%"D*").last >> "Craig"
``` ```
*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
changed in v1.3.0 as to avoid confusion with the new
[multipath](SYNTAX.md#multipaths) syntax. For backwards compatibility,
`#[...]` will continue to work until the next major release.*
## Result Type ## Result Type
GJSON supports the json types `string`, `number`, `bool`, and `null`. GJSON supports the json types `string`, `number`, `bool`, and `null`.
@ -263,7 +271,7 @@ For example:
..1 >> {"name": "Alexa", "age": 34} ..1 >> {"name": "Alexa", "age": 34}
..3 >> {"name": "Deloise", "age": 44} ..3 >> {"name": "Deloise", "age": 44}
..#.name >> ["Gilbert","Alexa","May","Deloise"] ..#.name >> ["Gilbert","Alexa","May","Deloise"]
..#[name="May"].age >> 57 ..#(name="May").age >> 57
``` ```
The `ForEachLines` function will iterate through JSON lines. The `ForEachLines` function will iterate through JSON lines.
@ -308,7 +316,7 @@ for _, name := range result.Array() {
You can also query an object inside an array: You can also query an object inside an array:
```go ```go
name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`) name := gjson.Get(json, `programmers.#(lastName="Hunter").firstName`)
println(name.String()) // prints "Elliotte" println(name.String()) // prints "Elliotte"
``` ```

View File

@ -89,25 +89,29 @@ friends.#.age [44,68,47]
### Queries ### Queries
You can also query an array for the first match by using `#[...]`, or find all matches with `#[...]#`. You can also query an array for the first match by using `#(...)`, or find all matches with `#(...)#`.
Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators, Queries support the `==`, `!=`, `<`, `<=`, `>`, `>=` comparison operators,
and the simple pattern matching `%` (like) and `!%` (not like) operators. and the simple pattern matching `%` (like) and `!%` (not like) operators.
```go ```go
friends.#[last=="Murphy"].first "Dale" friends.#(last=="Murphy").first "Dale"
friends.#[last=="Murphy"]#.first ["Dale","Jane"] friends.#(last=="Murphy")#.first ["Dale","Jane"]
friends.#[age>45]#.last ["Craig","Murphy"] friends.#(age>45)#.last ["Craig","Murphy"]
friends.#[first%"D*"].last "Murphy" friends.#(first%"D*").last "Murphy"
friends.#[first!%"D*"].last "Craig" 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. To query for a non-object value in an array, you can forgo the string to the right of the operator.
```go ```go
children.#[!%"*a*"] "Alex" children.#(!%"*a*") "Alex"
children.#[%"*a*"]# ["Sara","Jack"] children.#(%"*a*")# ["Sara","Jack"]
``` ```
*Please note that prior to v1.3.0, queries used the `#[...]` brackets. This was
changed in v1.3.0 as to avoid confusion with the new [multipath](#multipaths)
syntax. For backwards compatibility, `#[...]` will continue to work until the
next major release.*
### Dot vs Pipe ### Dot vs Pipe
@ -124,18 +128,18 @@ friends.0|first "Dale"
friends|0|first "Dale" friends|0|first "Dale"
friends|# 3 friends|# 3
friends.# 3 friends.# 3
friends.#[last="Murphy"]# [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}] 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 ["Dale","Jane"]
friends.#[last="Murphy"]#|first <non-existent> friends.#(last="Murphy")#|first <non-existent>
friends.#[last="Murphy"]#.0 [] friends.#(last="Murphy")#.0 []
friends.#[last="Murphy"]#|0 {"first": "Dale", "last": "Murphy", "age": 44} friends.#(last="Murphy")#|0 {"first": "Dale", "last": "Murphy", "age": 44}
friends.#[last="Murphy"]#.# [] friends.#(last="Murphy")#.# []
friends.#[last="Murphy"]#|# 2 friends.#(last="Murphy")#|# 2
``` ```
Let's break down a few of these. Let's break down a few of these.
The path `friends.#[last="Murphy"]#` all by itself results in The path `friends.#(last="Murphy")#` all by itself results in
```json ```json
[{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}] [{"first": "Dale", "last": "Murphy", "age": 44},{"first": "Jane", "last": "Murphy", "age": 47}]
@ -225,3 +229,30 @@ gjson.AddModifier("case", func(json, arg string) string {
"children.@case:lower.@reverse" ["jack","alex","sara"] "children.@case:lower.@reverse" ["jack","alex","sara"]
``` ```
#### Multipaths
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 multipath
```
{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
```
{"first":"Tom","age":37,"the_murphys":["Dale","Jane"]}
```