From 4d138e058b2959b28f3bed6fdeedf4a02f64d514 Mon Sep 17 00:00:00 2001 From: tidwall Date: Sun, 30 Jun 2019 12:59:56 -0700 Subject: [PATCH] Add multipath syntax --- README.md | 26 ++++++++++++++-------- SYNTAX.md | 65 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index ae2603f..17e0423 100644 --- a/README.md +++ b/README.md @@ -90,17 +90,25 @@ The dot and wildcard characters can be escaped with '\\'. "friends.1.last" >> "Craig" ``` -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. +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. + ``` -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" +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" ``` +*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 GJSON supports the json types `string`, `number`, `bool`, and `null`. @@ -263,7 +271,7 @@ For example: ..1 >> {"name": "Alexa", "age": 34} ..3 >> {"name": "Deloise", "age": 44} ..#.name >> ["Gilbert","Alexa","May","Deloise"] -..#[name="May"].age >> 57 +..#(name="May").age >> 57 ``` 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: ```go -name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`) +name := gjson.Get(json, `programmers.#(lastName="Hunter").firstName`) println(name.String()) // prints "Elliotte" ``` diff --git a/SYNTAX.md b/SYNTAX.md index c8e578f..d9d34c9 100644 --- a/SYNTAX.md +++ b/SYNTAX.md @@ -89,25 +89,29 @@ friends.#.age [44,68,47] ### 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, 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" +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"] +children.#(!%"*a*") "Alex" +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 @@ -124,18 +128,18 @@ 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 +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 +The path `friends.#(last="Murphy")#` all by itself results in ```json [{"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"] ``` +#### 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"]} +``` + +