-
Notifications
You must be signed in to change notification settings - Fork 6
Improve JsonPointer navigation and add JsonPointerGlob #291
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
base: main
Are you sure you want to change the base?
Conversation
Navigation of the document was done with JsonPointer tokens. Which was a list of Strings. Instead this has been refactored to use a `JsonPointer` class.
`JsonPointer`doesn't allow wildcards in the pointer. That is not an issue for `JsonPointer`'s in a schema. However, if we want to navigate a KsonValue using more expressive pointers we can't. Options to deal with this would be using `JsonPath`, `JmsePath`. However, before we commit to that I'd propose we use a simple improvement of `JsonPointer`, namely `JsonPointerPlus`. It adds the possibility to use wildcards `*`, and glob matching for a property key (only with ? (matching a single character) and * (matching all characters)).
JsonPointerPlus can now be used to navigate `KsonValues`'s!
We want to create our own JsonPointer language which extends the JsonPointer language from RFC 6901 with glob pattern matching. The name JsonPointerGlob captures that intention better.
used `*` spelled out before because it gave issues with kotlin documentation. By escaping one of the `**` we don't run into this anymore
literal tokens in JsonPointerGlob need to be escaped
dmarcotte
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this @holodorum! Added a few comments, but the headline is: this is fantastic.
src/commonMain/kotlin/org/kson/value/navigation/KsonValueNavigation.kt
Outdated
Show resolved
Hide resolved
src/commonMain/kotlin/org/kson/value/navigation/json_pointer/JsonPointerGlobParser.kt
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| // RecursiveDescent already handled remaining tokens, so we're done | ||
| return nextNodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This early return looks like it may surprise us in the future... could this be refactored so we either always return the result of the when or only return after we exit it? I'm worried this non-trivial, but not-like-the-others early return will be the root cause of some future bug as this code evolves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, what do you think of the refactor in c57bee4?
The doc contained an ambiguity where we escaped `/**` with `/\*\*` to prevent starting a new commnet block. However, that's also the way one would escape the asterisk in `JsonPointerGlob`.
the recursive descent was returned early which might surprise us in the future as @dmarcotte pointed out. This refactor makes it more explicit that `RecursiveDescent` tokens are handled differently from the other tokens.
Even though the language of `JsonPointerGlob` seems sensible and intuitive it could well be that we need to update and tweak it a bit. To signal that I've added an Experimental-annotation we opt-in to.
This PR improves handling of
JsonPointer. Instead of just passing a list of strings we use aJsonPointerclass.JsonPointeralways points to a single value in the document. However, it is useful to point to multiple values with a single 'query' or pointer string. The existing languages that allow for this, for examplejqorJMESPathseem overkill for what we want. We want a simple intuitive syntax. I came up withJsonPointerGlobwhich is a combination ofJsonPointerwith glob like features.JsonPointerGlob extends RFC 6901 JSON Pointer with:
*matches any single key or array index**matches zero or more levels*or**) is treated as a patternExamples:
JsonPointerGlob("")for root documentJsonPointerGlob("/users/*/email")for email of any user (wildcard, use*)JsonPointerGlob("/users/**/email")for all emails at any depth under users (recursive, use**)JsonPointerGlob("/**/email")for all emails anywhere in document (recursive)JsonPointerGlob("/users/*admin*/role")for role of users with "admin" in name (pattern)Recursive descent behavior: