Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve field values with multiple conditions #319

Open
ngarg-kr opened this issue Mar 21, 2023 · 5 comments
Open

Retrieve field values with multiple conditions #319

ngarg-kr opened this issue Mar 21, 2023 · 5 comments

Comments

@ngarg-kr
Copy link

For a sample payload like this:

{
  "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"]}
  ]
}

If we want to get the age of friend whose last name isMurphy and first name is Dale then what gjson expression will give that result.

I tried friends.#(last == "Murphy" && first == "Dale")#.age but it gives an empty array in response.

@tidwall kindly help regarding this

@volans-
Copy link

volans- commented Mar 21, 2023

@ngarg-kr you can chain queries for additional fields, so in your case with query:

friends.#(first=="Dale")#|#(last=="Murphy")#.age

you get:

[44]

See https://github.com/tidwall/gjson/blob/master/SYNTAX.md#queries and https://github.com/tidwall/gjson/blob/master/SYNTAX.md#dot-vs-pipe for additional information.

@ngarg-kr
Copy link
Author

@volans- Thanks! It worked

@sukant-kr
Copy link

@volans- @tidwall

This works for &&(and) condition, can we do something similar for || (or) condition.

Can you please suggest the expression for this:

friends.#(last == "Murphy" || first == "Dale")#.age

@volans-
Copy link

volans- commented Mar 21, 2023

@sukant-kr
Yes and no, as I've answered in #315 (comment), you can achieve the OR with multipaths and the @flatten modifier, but it would not prevent duplicates if results are matching both queries.

So for example with query:

friends.[#(first=="Dale")#,#(last=="Murphy")#]|@flatten.#.age

you get:

[44,44,47]

Because the first friend matches both queries.

You can at that point either get the parent objects and remove duplicates in your code.
Another approach is to avoid them in a query, but it becomes quite complex, basically I'm matching records with:

  • last==Murphy && first!=Dale
  • last!=Murphy && first==Dale
  • last==Murphy && first==Dale

and putting them together.

Here's the query:

friends.[#(last=="Murphy")#|#(first!="Dale")#,#(last!="Murphy")#|#(first=="Dale")#,#(last=="Murphy")#|#(first=="Dale")#].@flatten.#.age

and you get:

[47,44]

@taras-janea
Copy link

taras-janea commented Apr 4, 2023

Hi @volans-,

Guys, need your help.

package main

import (
	"fmt"

	"github.com/tidwall/gjson"
)

func main() {
	jsonStr := `{
  	"points": [
   	  {"x": 3, "y": 4, "z": 5, "description": "[3, 4, 5]"},
  	  {"x": 2, "y": 3, "z": 4, "description": "[2, 3, 4]"},
  	  {"x": 1, "y": 2, "z": 3, "description": "[1, 2, 3]"},
  	  {"x": 0, "y": 1, "z": 2, "description": "[0, 1, 2]"}
 	 ]
	}`

	result := gjson.Get(jsonStr, "points.#(x==3)")
	fmt.Println(result.Path(jsonStr))

	result = gjson.Get(jsonStr, "points.#(x==3)#|#(y==4)#|(z==5)")
	fmt.Println(result.Path(jsonStr))
}

Output:

points.0
@this

I desperately need to receive a path to queried result, but it's not returned for the query with multiple values.
I expect to receive points.0, but getting @this.
How can I query with multiple values and get the path for the result?

Thank you in advance,
Taras

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants