Feature Request: Some way to iterate across object properties (k, v) or at least get keys
scr-oath opened this issue · 7 comments
JSONPath-Plus has one feature that might help in this respect - the ~
modifier to the *
wildcard which returns keys or indices...
{
"foo": {
"abc": 1,
"def": 2
}
}
path, err := jp.ParseString("$.foo.*~")
if err != nil {
return err
}
keys := path.Get(data)
Alternatively, if Expr had a "ForEach" that could call a callback with key, value or index, value that would be useful too!
Or, if jp.Walk has a mechanism to do this - perhaps that could be used… hmm… maybe we could check the length of path? But… the issue is - when you walk the path may be unpredictable or different from what you expect? What if you could walk from a given jp.Expr - that would let you know the starting point and then be able to compare the length to that +1 to be the keys…
I guess this works - but is there any nicer way to get the path as a string than fmt.Sprint
?
func TestWalkLen(t *testing.T) {
const jsonData = `{"foo":{"bar":1,"baz":2, "buz":{"a":1,"b":2,"c":3}}}`
o, err := oj.ParseString(jsonData)
require.NoError(t, err)
jp.Walk(jp.C("foo").First(o), func(path jp.Expr, value any) {
if len(path) == 2 {
t.Log(fmt.Sprint(path[1]), value)
}
}, true)
}
=== RUN TestWalk2
keys_test.go:40: bar 1
keys_test.go:40: baz 2
--- PASS: TestWalk2 (0.00s)
PASS
Note that jp.Expr has a String()
method so you could just do t.Log(path[1:].String(), value)
.
I see. Frag
didn't have one and I didn't think of slice semantics 👏
However... I realize that I have an object with deep values and this does a lot of extra work ignoring all of the deeper leaves…
Do you have any ideas on an efficient way to traverse flatly - just the key value or index value pairs somehow?
Do any of the leaf names collide with each other? For example {x:1, y:{x:2}}
? If not then the last fragment of the path could be used otherwise you could turn the path into a string and use that as the key.
Did you figure it out on your own or do you want to continue?
Well the fallback technique is to just get the First and cast to map[string]any. Not terrible but I was just hopeful for flat for each iteration. You can close this one as less interesting than the other one I filed about bulk reshaping a la merging keys not clobbering the entire object