[Question] Any way to find the original full property path that got matched?
For eg (Pseudocode. Does not work)
const json = `
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}
`
value := gjson.Get(json, "friends.#.first")
fmt.Println(value.Array()[0].OriginalPath) //prints friends.0.first
The usefulness of this is when we're specifying wildcard matches
Sorry, but there isn't a built in way to get the full path back.
It could be useful to replace found values via sjson lib
+1, I would like to see this feature implemented.
I actually tried adding it myself but found the code way too hard to navigate. It also seems like this isn't possible right now, since array matches are stored as Raw strings and rebuilt during the call to arrayOrMap (I think), so there isn't enough information to rebuild the path, i.e. at which index it matched and with which sub-key.
This is a feature that I believe would be pretty awesome.
The main hurdle is that gjson, in most common cases, does not allocate any new memory during a Get call. This is a feature that is important to me and I try my darndest to keep in place. Tracking the original path for each Result would require constructing the path from each object or array component as the parser traverses the json document. While this is technically possible to do, it would cause users of this library to see performance be adversely affected.
Determining the original path from a Result following a Get operation is challenging.
The final Result that is returned from the Get function contains the raw json (stored in the Raw field), which is a slice of the original json. That in and of itself is not enough information to get the original path, at least not without performing some kind of exhaustive O(N) recursive operation that checks against every value in the original json document. That's possible but performance would be pretty bad.
A while back I included the Index field, which is the position of the Raw data in the original json, and more recently the Indexes field was added in PR #222 by @sspaink, which is like Index but for queries and paths that return multiple results as an array.
I think these two fields can be used to generate the original path by performing a fast reverse parse from the position of the Result.Raw in the original json.
Such as from the OP:
const json = `
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}
`
value := gjson.Get(json, "friends.#.first")
fmt.Println(value.Array()[0].Path(json))
// Output:
// friends.0.first
I just pushed an update that includes this feature.
const json = `
{
"name": {"first": "Tom", "last": "Anderson"},
"age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
]
}
`
value := Get(readmeJSON, "friends.#.first")
fmt.Println(value.Array()[0].Path(readmeJSON))
value = Get(readmeJSON, "friends.#.first")
fmt.Println(value.Paths(readmeJSON))
value = Get(readmeJSON, "friends.#(last=Murphy)")
fmt.Println(value.Path(readmeJSON))
value = Get(readmeJSON, "friends.#(last=Murphy)#")
fmt.Println(value.Paths(readmeJSON))
// Output:
// friends.0.first
// [friends.0.first friends.1.first friends.2.first]
// friends.0
// [friends.0 friends.2]