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

Singular path as selector #522

Open
gregsdennis opened this issue May 27, 2024 · 14 comments
Open

Singular path as selector #522

gregsdennis opened this issue May 27, 2024 · 14 comments

Comments

@gregsdennis
Copy link
Collaborator

Inspired by a StackOverflow question, I think a singular path could be a viable selector.

The example given is

addresses[productData.products[0].addressRefId].storeName

I see this as taking the value in productData.products[0].addressRefId as the selector value.

This would, for example, allow the data to contain the index of an array (or the key of an object) to select, amongst other similar functionality.

If we could work out a way to support multi-value paths, that'd be cool, but I think singular paths are simple enough to do.

@He-Pin
Copy link

He-Pin commented May 27, 2024

But it can be expressed with the filter with test-expr.

@vishalJ16
Copy link

@He-Pin Can you please help with the expression. I tried multiple ways drawing inspiration from here #156 but could not come up with a working one, because none of the method could give me the value of inner path productData.products[0].addressRefId , to be used as a "key" for outer path addresses["inner path evaluated value"].storeName

@jg-rp
Copy link

jg-rp commented May 27, 2024

I like this syntax.

Equivalent results could be achieved using a filter selector and a non-standard key/index identifier or function. I've tried to describe such a current key identifier here (# is the name or index associated with @).

$.addresses[?# = $.productData.products[0].addressRefId].storeName

But a singular path being coerced to a name or index selector looks nicer to me.

@He-Pin
Copy link

He-Pin commented May 27, 2024

@vishalJ16 I think the root cause is current filter selector only works on the member's value,
We are facing the same problem ,and we are using [/$regexExp/$flags] to match the keys (only works on a JSON object)`

I would like to have a key filter, something like the @ but point to the member's name or idx.

Updated:
I think @jg-rp 's idea is great:

  1. @ refs to the member value
  2. # refs to member name / index

Another thing we need to address is , how to pass the # to the current function definition, maybe we need add something to the type system.

@vishalJ16
Copy link

@He-Pin
What essentially you meant is @jg-rp expression is something which could have worked, but currently it's not possible, am I correct?
And is it right to conclude that my requirement is not possible with the current version of jayway-jsonpath and It requires a code change?

@He-Pin
Copy link

He-Pin commented May 27, 2024

@He-Pin
What essentially you meant is @jg-rp expression is something which could have worked, but currently it's not possible, am I correct?
And is it right to conclude that my requirement is not possible with the current version of jayway-jsonpath and It requires a code change?

With jayway, it's possibly, you need to register a pathfunction with reflection.

@jg-rp
Copy link

jg-rp commented May 27, 2024

how to pass the # to the current function definition, maybe we need add something to the type system.

@He-Pin I've been treating the result of # as a ValueType, so standard functions that accept a ValueType can be used without modification.

$[?match(#, 'ab.*')]

An alternative might be to allow function extensions to accept a union of types for a parameter. Then, for example, match() could be defined to take an argument of ValueType | KeyType for its first parameter, and ValueType for the second.

@jg-rp
Copy link

jg-rp commented May 28, 2024

Here's my attempt at describing a singular query selector.

I'm still undecided as to whether the root identifier should be explicit or implicit for embedded queries. If the embedded query starts with a bracketed selection, the $ might make it easier to read.

$.a.j[$['c d'].x.y]

vs

$.a.j[['c d'].x.y]

Singular Query Selector

The singular query selector consist of an embedded absolute singular query, the result of which is used as an object member name or array element index.

If the embedded query resolves to a string or int value, at most one object member value or array element value is selected. Otherwise the singular query selector selects nothing.

Syntax

selector                = name-selector /
                          wildcard-selector /
                          slice-selector /
                          index-selector /
                          filter-selector /
                          singular-query-selector

singular-query-selector = abs-singular-query

Examples

{
  "a": {
    "j": [1, 2, 3],
    "p": {
      "q": [4, 5, 6]
    }
  },
  "b": ["j", "p", "q"],
  "c d": {
    "x": {
      "y": 1
    }
  }
}
Query Result Result Path Comment
$.a[$.b[1]] {"q": [4, 5, 6]} $['a']['p'] Object name from embedded singular query
$.a.j[$['c d'].x.y] 2 $['a']['j'][1] Array index from embedded singular query
$.a[$.b] Embedded singular query does not resolve to a string or int value

@vishalJ16
Copy link

With jayway, it's possibly, you need to register a pathfunction with reflection

Sorry I am a bit confused. To register my custom function to jsonpath, I would required these code changes json-path/JsonPath#286 mentioned here json-path/JsonPath#246, or can it be done without them? These changes still not merged.

@He-Pin
Copy link

He-Pin commented May 28, 2024

With jayway, it's possibly, you need to register a pathfunction with reflection

Sorry I am a bit confused. To register my custom function to jsonpath, I would required these code changes json-path/JsonPath#286 mentioned here json-path/JsonPath#246, or can it be done without them? These changes still not merged.

You can change it with Java Reflection or MrthodHandles。

@f3ath
Copy link

f3ath commented May 31, 2024

FWIW, in my implementation I allow custom functions to be provided to the parser, with some available almost out-of-the-box:

    {
      "name": "key(), palindromic keys",
      "selector" : "$[?key(@) == reverse(key(@))]",
      "document" : {"foo": "FOO", "bar": "BAR", "bab":  "BAB", "": "", "a":  "A"},
      "result": ["BAB","","A"]
    },

@gregsdennis
Copy link
Collaborator Author

@f3ath, that doesn't pertain to this issue. This issue is about creating a new selector that is itself a path, not custom functions.

@gregsdennis
Copy link
Collaborator Author

@jg-rp, we have another issue for grabbing the key in an expression. Arguably, that allows for more functionality, but unfortunately it hasn't been received well.

@gregsdennis
Copy link
Collaborator Author

gregsdennis commented May 31, 2024

@jg-rp you bring up a good point about including the root selector. I think it should be required.

I wonder if the relative root makes sense to also define.

$..[@.a]

Recursively select the value in objects indicated by the object's a property.

Of course this entire feature can also only be defined for keys which are strings (names) or numbers (indices). It wouldn't select anything if the value ends up being any other JSON value type.

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

5 participants