Skip to content

Conversation

@holodorum
Copy link
Collaborator

This PR improves handling of JsonPointer. Instead of just passing a list of strings we use a JsonPointer class. JsonPointer always 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 example jq or JMESPath seem overkill for what we want. We want a simple intuitive syntax. I came up with JsonPointerGlob which is a combination of JsonPointer with glob like features.

JsonPointerGlob extends RFC 6901 JSON Pointer with:

  • Wildcard tokens: A token that is exactly * matches any single key or array index
  • Recursive descent: A token that is exactly ** matches zero or more levels
  • Glob patterns: A token containing * or ? (but not only * or **) is treated as a pattern
  • RFC 6901 escaping: still supported for compatibility

Examples:

  • JsonPointerGlob("") for root document
  • JsonPointerGlob("/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:

  • Matches zero or more path segments (object keys or array indices)
  • Performs depth-first traversal through the document tree
  • Performance: O(n) where n is the size of the subtree being searched

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
Copy link
Contributor

@dmarcotte dmarcotte left a 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.

}

// RecursiveDescent already handled remaining tokens, so we're done
return nextNodes
Copy link
Contributor

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.

Copy link
Collaborator Author

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

Successfully merging this pull request may close these issues.

2 participants