Repository navigation
fix(json-formatter): find JSONPath quoted names with escapes, brackets or the other quote - #410
Merged
anurag629 merged 1 commit intoOct 28, 2026
Conversation
…s or the other quote jsonpath-plus splits an expression with regular expressions, so a quoted name holding a quote, a backslash, a bracket or a comma, or one that reads like an operator (*, .., ^, ~, $, 1:2), found nothing or ran as the operator. Quoted names are now read as RFC 9535 string literals. A name the library already read correctly is left as written. Any other is swapped for an alias that is also added, hidden, to the parsed data, and the real key is put back in the matches, the pointer and the path. buildJsonTreePath now quotes a key called $, which was written as .$ (the root). Closes codercops#405
anurag629
approved these changes
Oct 28, 2026
anurag629
left a comment
Member
There was a problem hiding this comment.
Thanks @Saifjafri212213, smart way around the library. Lint (develop's 11 warnings), all 2417 tests, the build and the pages pass on top of develop. All six paths from #405 find their value, a round trip through buildJsonTreePath works for 31 awkward keys (quotes, backslashes, brackets, *, .., ^, ~, $, a,b, 1:2, ?(@), emoji, a private-use character and more), and 22 ordinary expressions (wildcards, .., slices, unions, filters, $.*~, big numbers) give exactly the same results as develop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes JSONPath quoted names that hold escapes, brackets, the other quote, or that look like an operator. All six paths from the issue now find their value, and so does the path
buildJsonTreePathwrites for any key I tried.Closes #405
Cause
lib/jsonpath.tsonly wrapsjsonpath-plus, and the library cuts an expression up with regular expressions (JSONPath.toPathArray). It does not decode escapes, and a name with a quote, a bracket or a comma is split in the wrong place ($["br[ack]et"]becomes the segmentsbrandacket"). Worse, its_traceruns a segment such as*,..,^,~,$,1:2or?(...)as an operator, so$["*"]is a wildcard and not the key*. Fixing only the splitting would still leave those wrong.What changed
lib/jsonpath.ts: a bracket that holds exactly one quoted name is read as an RFC 9535 string literal (in double quotes'needs no escape and\"is a quote, in single quotes the other way round, and\\ \/ \b \f \n \r \t \uXXXXwork in both;[ ] . ,inside quotes are characters; blanks inside the brackets are allowed)._, space,-, no escape) is left exactly as written, so nothing that worked changes.*,..,~,Object.keysand filters never see it. The real key goes back into the matches, the pointer (with~0/~1escaping) and the displayed path.\uXXXX) or in the expression, so it cannot collide with a key or a value.lib/json-tree-path.ts:buildJsonTreePathwrote a key called$as$.$, and the second$is the root, not the key. It is now written as$["$"]. Every other key is written as before.Notes for review
\uD800are accepted (RFC 9535 says they are invalid), becauseJSON.stringifywrites a key that has one that way and the tree path has to find it.$['it's']), as it already does for$.*on those keys. Happy to change that if you want them re-usable.$['a','b']);jsonpath-plusfinds nothing for it today, and a test makes sure it is not shortened to its first name.How I Tested This
lib/__tests__/jsonpath.test.tsnow covers: the six paths from the issue, the four that already worked, every escape,[ ] . ,inside quotes, names that look like operators (* .. ^ ~ $ @ 1:2 ?(@.x) (1)), the pathbuildJsonTreePathwrites for 50 awkward keys (including~0,~1,__proto__, control characters, lone surrogates, astral and non-Latin characters) as a root key and as nested keys and array indexes, wildcard,..and filters after a name,~on a name, the result path, large numbers staying exact, blanks inside brackets, an escape in an otherwise plain name, two awkward names in one path, a document that already uses the private-use characters (as itself and as escapes in either case), a filter that mentions the alias, scalar and array roots, an unreadable escape keeping its old result, unions not being shortened, and a wildcard over an object that has a lookup.developon 12,000 random expressions (8,764 distinct) over four documents, using wildcards,.., filters, slices, unions,^,~and quoted names: all 1,186 expressions that returned something before give identical matches and paths. The only differences are 111 expressions that now find a quoted awkward key or one with blanks inside the brackets, and 3 that now reach the script selector[(@.length-1)]and hit its existingloc.indexOf is not a functionerror (the old code gives the same error for$['a b'][(@.length-1)]).\uhandling, string and escape skipping inbracketEnd, blank handling, the union guard, the alias being enumerable or only on the root, each pointer escape, un-aliasing of values and paths, and each of the three sentinel checks) and checked a test fails for each. Two survived as equivalent mutants: the\uhex check (the slice is always four characters), and de-duplicating aliases, which I removed because it only changed the cost.*,a,band$) found exactly one match with the right value. The six paths from the issue found their values, and a deep path throughit's,a.bandc]found99. No console errors.tscis clean, lint is at develop's 11 warnings, the full suite passes (2407 tests) andnext buildsucceeds. The CI check for a BOM or garbled characters finds nothing.AI assistance
An AI coding assistant helped write the fix and the tests. I checked the library's behaviour in its source, ran the comparison and mutation checks above, and tried the tree-to-JSONPath flow in the app.