Skip to content

Commit

Permalink
Add option to jp.Walk for leaves only (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
ohler55 authored Nov 9, 2023
1 parent 7e79b01 commit 4f98673
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

The structure and content of this file follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [1.20.3] - 2023-11-09
### Added
- Added an option to jp.Walk to just callback on leaves making the function more useable.

## [1.20.2] - 2023-10-30
### Fixed
- A script of `@.x` is now read correctly as `@.x exists true`.
Expand Down
47 changes: 38 additions & 9 deletions jp/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,69 @@ package jp
import (
"time"

"github.com/ohler55/ojg/alt"
"github.com/ohler55/ojg/gen"
)

// Walk data and call the cb callback for each node in the data. The path is
// reused in each call so if the path needs to be save it should be copied.
func Walk(data any, cb func(path Expr, value any)) {
func Walk(data any, cb func(path Expr, value any), justLeaves ...bool) {
path := Expr{Root('$')}
walk(path, data, cb)
walk(path, data, cb, 0 < len(justLeaves) && justLeaves[0])
}

func walk(path Expr, data any, cb func(path Expr, value any)) {
cb(path, data)
func walk(path Expr, data any, cb func(path Expr, value any), justLeaves bool) {
top:
switch td := data.(type) {
case nil, bool, int64, float64, string,
int, int8, int16, int32, uint, uint8, uint16, uint32, uint64, float32,
[]byte, time.Time:
// leaf node
cb(path, data)
case []any:
if !justLeaves {
cb(path, data)
}
pi := len(path)
path = append(path, nil)
for i, v := range td {
walk(append(path, Nth(i)), v, cb)
path[pi] = Nth(i)
walk(path, v, cb, justLeaves)
}
case map[string]any:
if !justLeaves {
cb(path, data)
}
pi := len(path)
path = append(path, nil)
for k, v := range td {
walk(append(path, Child(k)), v, cb)
path[pi] = Child(k)
walk(path, v, cb, justLeaves)
}
case gen.Array:
if !justLeaves {
cb(path, data)
}
pi := len(path)
path = append(path, nil)
for i, v := range td {
walk(append(path, Nth(i)), v, cb)
path[pi] = Nth(i)
walk(path, v, cb, justLeaves)
}
case gen.Object:
if !justLeaves {
cb(path, data)
}
pi := len(path)
path = append(path, nil)
for k, v := range td {
walk(append(path, Child(k)), v, cb)
path[pi] = Child(k)
walk(path, v, cb, justLeaves)
}
case alt.Simplifier:
data = td.Simplify()
goto top
default:
// TBD use reflection
cb(path, data)
}
}
19 changes: 17 additions & 2 deletions jp/walk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,31 @@ import (

"github.com/ohler55/ojg/gen"
"github.com/ohler55/ojg/jp"
"github.com/ohler55/ojg/pretty"
"github.com/ohler55/ojg/sen"
"github.com/ohler55/ojg/tt"
)

type simple int

func (s simple) Simplify() any {
return map[string]any{"x": int64(s)}
}

type other int

func TestWalk(t *testing.T) {
data := map[string]any{"a": []any{1, 2, 3}, "b": nil}
data := map[string]any{"a": []any{1, 2, 3}, "b": nil, "c": simple(4), "d": other(5)}
var paths []string
jp.Walk(data, func(path jp.Expr, value any) { paths = append(paths, path.String()) })
sort.Strings(paths)
tt.Equal(t, `[$ $.a "$.a[0]" "$.a[1]" "$.a[2]" $.b]`, string(sen.Bytes(paths)))
tt.Equal(t, `[$ $.a "$.a[0]" "$.a[1]" "$.a[2]" $.b $.c $.c.x $.d]`, string(sen.Bytes(paths)))

leaves := map[string]any{}
jp.Walk(data, func(path jp.Expr, value any) {
leaves[path[1:].String()] = value
}, true)
tt.Equal(t, `{"a[0]": 1 "a[1]": 2 "a[2]": 3 b: null c.x: 4 d: 5}`, pretty.SEN(leaves))
}

func TestWalkNode(t *testing.T) {
Expand Down
2 changes: 0 additions & 2 deletions notes
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@



- script.go
- API to add functions
- RegisterUnaryFunction(name string, get bool, f func(arg any) any)
Expand Down

0 comments on commit 4f98673

Please sign in to comment.