Problem statement
Using Elisp, when point is on an element in a JSON datastructure (either raw JSON or an Elisp sexp of the kind generated by json.el), is there an easy way to get a json-pointer-get-style path to that element?
Sexp example
To take the example from the json-pointer.el docs:
(let ((json '((foo . 1)
(bar . [((qux . "hello")) 3])
(baz . ((boo . [1 3 5 7]))))))
(json-pointer-get json "/foo") ;; => 1
(json-pointer-get json "/bar/0") ;; => '((qux . "hello"))
(json-pointer-get json "/bar/0/qux") ;; => "hello"
(json-pointer-get json "/bar/1") ;; => 3
(json-pointer-get json "/baz/boo/2")) ;; => 55
If point was on the "1"
on the first line, I'd like to get "/foo"
.
If point was on the first opening parenthesis or last closing parenthesis inside the square brackets of the second line, I'd like to get "/bar/0"
.
If point was somewhere on "hello"
, I'd like to get "/bar/0/qux"
.
If point was on the "3"
on the second line, I'd like to get "/bar/1"
.
And if point was on the "5"
on the third line, I'd like to get "/baz/boo/2"
.
Raw JSON example
I'd also like to get the same paths when point is positioned on the same elements in raw JSON format instead of an Elisp sexp.
In other words, if my buffer contained the raw JSON equivalent of the above sexp:
{"foo":1, "bar":[{"qux":"hello"}, 3], "baz":{"boo":[1, 3, 5, 7]}}
If point was on the first "1"
, I'd like to get "/foo"
.
If point was on the opening or closing curly braces following "bar", I'd like to get "/bar/0"
.
If point was somewhere on "hello"
, I'd like to get "/bar/0/qux"
.
If point was on the "3"
in the second element of "bar", I'd like to get "/bar/1"
.
And if point was on the "5"
, I'd like to get "/baz/boo/2"
.
Naturally, this should work regardless of the whitespace and should work just as well if everything was one one line or spread across multiple lines.