JsonPath-PHP icon indicating copy to clipboard operation
JsonPath-PHP copied to clipboard

Returning key of found object

Open bwl21 opened this issue 3 years ago • 11 comments

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?

bwl21 avatar Apr 07 '21 12:04 bwl21

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).

Galbar avatar Apr 07 '21 12:04 Galbar

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.

bwl21 avatar Apr 07 '21 13:04 bwl21

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.

Galbar avatar Apr 07 '21 13:04 Galbar

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.

bwl21 avatar Apr 07 '21 14:04 bwl21

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 😄

Galbar avatar Apr 07 '21 16:04 Galbar

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..

bwl21 avatar Apr 07 '21 21:04 bwl21

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 avatar Apr 07 '21 22:04 Galbar

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!

Galbar avatar Apr 14 '21 15:04 Galbar

@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.

bwl21 avatar Apr 14 '21 15:04 bwl21

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.

Galbar avatar Apr 21 '21 21:04 Galbar

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

#59

drugan avatar Jun 30 '22 09:06 drugan