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

Returning key of found object #46

Open
bwl21 opened this issue Apr 7, 2021 · 11 comments
Open

Returning key of found object #46

bwl21 opened this issue Apr 7, 2021 · 11 comments

Comments

@bwl21
Copy link
Contributor

bwl21 commented Apr 7, 2021

suppose I have

{
"a": {
   "v": "va"
    },
"b": {
   "v": "vb"
    }
}

$..[?(@.v=="va")] returns

[
{
	"v":"va"
}
]

how can I get the key of this object which is a ?

https://extendsclass.com/jsonpath-tester.html suports ~, such that $..[?(@.v=="va")]~ returns

[
"a"
]

How can I do this in JsonPath-PHP?
@Galbar
Copy link
Owner

Galbar commented Apr 7, 2021

This is not doable with JsonPath-PHP. I looked around and it does not seem to be part of the spec anywhere other than in the library backing the site you are sharing. If you check the readme it states that it is an addition, not provided in the spec.

Aside from that, feel free to implement it and open a PR with it. We can discuss what it should work like and the edge cases. I tried doing:

  • $.house.room~.length expecting 4 but got room
  • $.house.room.~ not only returns the keys of the children but also itself

Overall it seems to be a quirky functionality in the way it is implemented in that library. If we were to include it in JsonPath-PHP I'd expect a better definition (similar to how we included .length a year ago).

@bwl21
Copy link
Contributor Author

bwl21 commented Apr 7, 2021

I do not insist in a particular solution, but I do have the problem to get the key of objects in the result set.

Do you have an Idea of a workaround?

The ^and ~ are proposed in https://github.com/JSONPath-Plus/JSONPath.

There is one more thing which confuses me.

php app/test.php "$..*[?(@.price==22.99)]" works fin in JsonPath-PHP but $..[?(@.price==22.99)] does not yield a result.

in https://extendsclass.com/jsonpath-tester.html both expressions yield the same results.
It appears to m that [] in jsonpath is either a step or a predicate.

@Galbar
Copy link
Owner

Galbar commented Apr 7, 2021

Do you have an Idea of a workaround?

I don't think it is possible to do the equivalent of ~ with the current implementation of this library. Implementing it should not be overly complex, though. Honestly, I never thought of this usecase before 😅.

^ operator is also not available, but you can always do a subquery with more than one level. For example, say you want to get all objects that have a price ($..price^ ), you can do $..*[?(@.price)]. For more levels up just add more levels down in the subquery.

..* vs. ..

I remember thinking about this one for quite a while when I implemented the library. My conclusion was that .. should behave as . but recursive. You can see this in the syntax definition of the language implemented by this library:

childname   = '.' (var_name | '*')
recursive   = '..' (var_name | '*')

The logic behind this is that in the same way you can't do foo.[1] in js, you can't do $.foo.[1] in jsonpath and, because .. should behave the same, you can't have $..[1] but you can have $..*[1], which is equivalent but different because * is a valid variable name with special meaning. Following the logic above, you can do $.foo..price, because foo.price is valid in js.

@bwl21
Copy link
Contributor Author

bwl21 commented Apr 7, 2021

thanks for the hint wrt ^ I will try this.
It would be of help if I could get the canonical jsonpath of the result as it is provided in https://jsonpath.com/.

thanks for the explanation about ... It sounds reasonable to me, but it is not compatible with other implementations. So one is stuck.

@Galbar
Copy link
Owner

Galbar commented Apr 7, 2021

cannonical jsonpath

compatibility with other implementations

As I've said before, I implemented this before there were the number of implementations that exist today. I don't have the time to update this library to match other implementations' features.

Of course, PRs are very welcome 😄

@bwl21
Copy link
Contributor Author

bwl21 commented Apr 7, 2021

that have a price ($..price^ ), you can do $..*[?(@.price)]. For more levels up just add more levels down in the subquery.

with

{"feldnamen": {
    "familienname": {
      "sample":"Bitter-Schwalenst\u00f6cker",
      "ctabbildung":"dbfeld",
      "ctmerkmalsgruppe":"",
      "ctdbfeldnam":"name",
      "ctfunktion":"ct_getnachname",
      "cthinweis":""
   }    
}}

$..*[?(@.ctabbildung == "dbfeld")] finds the `familienname``

but $..familienname[?(@.ctabbildung == "dbfeld")] does not yield a result.

This also happens in https://jsonpath.com/ but I cannot see why.

So in datastructures which uses keys as values (such as familienname I still cannot find out how to retrieve objects based on the key and properties of this key..

@Galbar
Copy link
Owner

Galbar commented Apr 7, 2021

In [?(@.ctabbildung == "dbfeld")], @ is the value of each child of $..familienname.

With $..familienname[?(@.ctabbildung == "dbfeld")] you are looking for something like $..familienname.*.ctabbildung: "dbfeld", but what you want is $..familienname.ctabbildung: "dbfeld".

I think the query you are looking for is $..*[?(@.familienname.ctabbildung == "dbfeld")].familienname.

@Galbar
Copy link
Owner

Galbar commented Apr 14, 2021

hi @bwl21,

Let me know if my last message solved your question.

Regarding the ~ operator, I don't have the time right now to implement it. If you have the time, feel free to open a PR for it.

Cheers!

@bwl21
Copy link
Contributor Author

bwl21 commented Apr 14, 2021

@Galbar thanks for asking, I did not answer yet since I am still trying around but did not get the full understanding.

Nevertheless. What I want is the keys of all objects which have a property ctabbildungwith the value of dbfeld. For exsamle familienname.

so I tried $..*[?(@.*.ctabbildung == "dbfeld")] and then read the array_keys of the result but still was not successful.

@Galbar
Copy link
Owner

Galbar commented Apr 21, 2021

Hi @bwl21 I don't think there is a way to get the keys using this JSONPath implementation. I think the solution for this would be to add the ~ operation to this implementation.

I have an idea on how to implement the ~ operator but I don't have the time right now. I'm sorry.

The idea would be to duplicate the access operators (.<child_name>, [...], ..*, etc.) and add a ~ at the end of the regexes and duplicate functions to return the keys instead of the values in the array.

@drugan
Copy link

drugan commented Jun 30, 2022

I am not sure if that is relevant to this issue but may be someone will find it useful:

#59

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

3 participants