{"id":17299002,"url":"https://github.com/egibs/deepwalk","last_synced_at":"2026-05-06T07:35:22.917Z","repository":{"id":189425499,"uuid":"680662290","full_name":"egibs/deepwalk","owner":"egibs","description":"Traverse data structures and retrieve values in Golang or via CLI","archived":false,"fork":false,"pushed_at":"2024-10-29T21:29:26.000Z","size":167,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-29T23:43:58.092Z","etag":null,"topics":["cli","cobra","cobra-cli","go","golang","json","map","maps","parsing","slice","struct"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/egibs/deepwalk","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/egibs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-20T01:32:03.000Z","updated_at":"2024-10-29T21:29:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"8dd9bd81-c9e7-4a93-a4c7-5187af449010","html_url":"https://github.com/egibs/deepwalk","commit_stats":null,"previous_names":["egibs/deepwalk"],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egibs%2Fdeepwalk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egibs%2Fdeepwalk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egibs%2Fdeepwalk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/egibs%2Fdeepwalk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/egibs","download_url":"https://codeload.github.com/egibs/deepwalk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245737039,"owners_count":20664025,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","cobra","cobra-cli","go","golang","json","map","maps","parsing","slice","struct"],"created_at":"2024-10-15T11:20:44.450Z","updated_at":"2026-05-06T07:35:17.879Z","avatar_url":"https://github.com/egibs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# deepwalk\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/egibs/deepwalk.svg)](https://pkg.go.dev/github.com/egibs/deepwalk)\n\n## Overview\n\n`deepwalk` is a Golang implementation of the code documented [here](https://egibs.xyz/posts/technical/deep_walk/) which was originally written in Python.\n\nThe goal of `deepwalk` is to traverse an arbitrarily-nested map and retrieve the value associated with a given key.\n\nThis project was mostly done to hack on some Go after spending awhile way from it. That said, this package is still useful aside from the \"see if it works\" perspective.\n\nUsage examples can be found in `pkg/traverse/traverse_test.go`, but because code is only as good as its documentation, examples will be added (and added to) below.\n\n## Installation\n\nTo install `deepwalk`, run the following:\n```sh\ngo install github.com/egibs/deepwalk/v2@latest\n```\n\nImport `traverse` like so:\n```go\nimport (\n    \"github.com/egibs/deepwalk/pkg/v2/traverse\"\n)\n```\n\nOr, use the provided Dockerfile:\n```\nmake build-docker\n```\n\nthen:\n```\ndocker run deepwalk:latest\n```\n\n## Examples\n\nThe original use-case for this in Python was to traverse Python dictionaries. While Golang has different names and conventions for this, the approach remains the same.\n\n### CLI\n\n[Cobra](https://github.com/spf13/cobra) is used to provide CLI support for `deepwalk`.\n\nTo get started, build the `deepwalk` binary with `make build`.\n\nThen, run `deepwalk` to see the available commands:\n\n```sh\n❯ ./deepwalk -h\nUsage:\n  deepwalk [command]\n\nAvailable Commands:\n  completion  Generate the autocompletion script for the specified shell\n  help        Help about any command\n  traverse    Traverse an object for the specified key and return the value associated with that key\n\nFlags:\n  -h, --help   help for deepwalk\n\nUse \"deepwalk [command] --help\" for more information about a command.\n```\n\nTo use `Traverse`, use the `traverse` command:\n```sh\n./deepwalk traverse -h\ntraverse utilizes the Traverse function which requires a ReturnControl value to determine what to return.\n\t\tFirst will return the first value found, Last will return the last value found, and All will return all values found.\n\nUsage:\n  deepwalk traverse --object \u003cfilename or JSON string\u003e --search-key \u003csearch key\u003e --default-value \u003cdefault value\u003e --return-value \u003creturn value\u003e [flags]\n\nFlags:\n      --default-value string   Default value to return if search fails (default \"NO_VALUE\")\n  -h, --help                   help for traverse\n      --object string          Object to search\n      --return-value string    Value to return if search succeeds (default \"all\")\n      --search-key string      Key to search for\n```\n\nExamples of using `traverse`:\n`search`:\n```sh\n❯ ./deepwalk traverse  --object complex.json --search-key name\n[\n  \"Tamra Bennett\",\n  \"Alana Hoover\",\n  \"Ewing Williamson\",\n  \"Webster Serrano\",\n  \"Lea Bryant\",\n  \"Sylvia Parks\",\n  \"Hubbard Delgado\",\n  \"Townsend Calderon\",\n  \"Knapp Patton\",\n  \"Barr Floyd\",\n  \"Haynes Osborn\",\n  \"Rebecca Walters\",\n  \"Muriel Lindsay\",\n  \"Osborne Reid\",\n  \"Lois Chaney\",\n  \"Contreras Wolfe\",\n  \"Goodwin Christensen\",\n  \"Rosa Luna\",\n  \"Tabitha Moreno\",\n  \"Oneil Carlson\"\n]\n\n❯ ./deepwalk traverse --object '{\"a\": {\"b\": \"c\"}}' --search-key b\n\"c\"\n```\n\n### JSON\nGiven a simple JSON object like this:\n```go\nvar exampleJSON = []byte(`{\n    \"key\": [\n        {\n            \"inner_key\": \"value\"\n        }\n    ]\n}`)\n```\n\nThe value of `inner_key` can be retrieved like so:\n```go\nvar object map[string]interface{}\nerr := json.Unmarshal(exampleJSON, \u0026object)\nif err != nil {\n    fmt.Println(err)\n}\nvalue, err := deepwalk.Traverse(object, \"key\", \"\u003cNO_VALUE\u003e\", traverse.All)\nif err != nil {\n    fmt.Println(err)\n}\nfmt.Println(value)\n```\nwhich will result in `value` being printed.\n\nTo add some color to the aruguments used when calling `Traverse` --\n* `object` is the starting map to traverse\n* `key` is the target key to search for in the structure\n* `\u003cNO_VALUE\u003e` is the default value to return if the desired value is not found\n* `all` specifies the values to return, if found\n  * `first` and `last` are also available which will return the first and last found values, respectively\n\n### Maps\n\nMaps can be used directly as well (this example is taken from the tests) --\n```go\nvar exampleMap = map[string]interface{}{\n\t\"key\": map[string]interface{}{\n\t\t\"inner_key\": []interface{}{\n\t\t\t[]interface{}{\n\t\t\t\t[]interface{}{\n\t\t\t\t\tmap[string]interface{}{\n\t\t\t\t\t\t\"very_nested_key\": \"very_nested_value\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n\nvalue, err := deepwalk.Traverse(obj, \"very_nested_key\", \"\u003cNO_VALUE\u003e\", traverse.All)\nif err != nil {\n    fmt.Println(err)\n}\nfmt.Println(value)\n```\n\n### Structs\n\nStructs can also be traversed with `Traverse`:\n```go\ntype TestStruct struct {\n    Field1       string\n    Field2       int\n    NestedStruct struct {\n        NestedStruct2 struct {\n            NestedField1 string\n            NestedField2 int\n        }\n        NestedField1 string\n        NestedField2 int\n    }\n}\n\ntestStruct := TestStruct{\n    Field1: \"test\",\n    Field2: 123,\n    NestedStruct: struct {\n        NestedStruct2 struct {\n            NestedField1 string\n            NestedField2 int\n        }\n        NestedField1 string\n        NestedField2 int\n    }{\n        NestedStruct2: struct {\n            NestedField1 string\n            NestedField2 int\n        }{\n            NestedField1: \"nested\",\n            NestedField2: 456,\n        },\n        NestedField1: \"nested\",\n        NestedField2: 456,\n    },\n}\n\nvalue, err := deepwalk.Traverse(testStruct, \"NestedField1\", \"\u003cNO_VALUE\u003e\", traverse.All)\nif err != nil {\n    fmt.Println(err)\n}\nfmt.Println(value)\n```\n\n## Testing\nSeveral categories of tests are included:\n1. 7 test cases covering a variety of uses\n2. Randomly-generated test cases for successful path-based traversal\n3. Randomly-generated test cases for traversals that return a default value\n\nCategories three and four run one-thousand iterations of each variant and each distinct case uses a randomly-generated map structure, list of keys, and desired value (in the case of the path-based traversal tests)\n\nRun all of the included tests by running `make test`:\n```sh\n❯ make test\ngo test ./... -v\ngo: downloading github.com/wk8/go-ordered-map/v2 v2.1.8\ngo: downloading github.com/spf13/cobra v1.8.0\ngo: downloading github.com/spf13/pflag v1.0.5\ngo: downloading gopkg.in/yaml.v3 v3.0.1\ngo: downloading github.com/bahlo/generic-list-go v0.2.0\ngo: downloading github.com/buger/jsonparser v1.1.1\ngo: downloading github.com/mailru/easyjson v0.7.7\n?       github.com/egibs/deepwalk/v2    [no test files]\n?       github.com/egibs/deepwalk/v2/cmd        [no test files]\n?       github.com/egibs/deepwalk/v2/internal/util      [no test files]\n=== RUN   TestTraverse\n=== RUN   TestTraverse/Test_case_1_-_key_found_in_map\n=== RUN   TestTraverse/Test_case_2_-_key_not_found_in_map\n=== RUN   TestTraverse/Test_case_3_-_key_found_in_nested_map\n=== RUN   TestTraverse/Test_case_4_-_key_not_found_in_nested_map\n=== RUN   TestTraverse/Test_case_5_-_key_found_in_struct\n=== RUN   TestTraverse/Test_case_6_-_key_not_found_in_struct\n=== RUN   TestTraverse/Test_case_7_-_duplicate_key_found_in_map\n--- PASS: TestTraverse (0.00s)\n    --- PASS: TestTraverse/Test_case_1_-_key_found_in_map (0.00s)\n    --- PASS: TestTraverse/Test_case_2_-_key_not_found_in_map (0.00s)\n    --- PASS: TestTraverse/Test_case_3_-_key_found_in_nested_map (0.00s)\n    --- PASS: TestTraverse/Test_case_4_-_key_not_found_in_nested_map (0.00s)\n    --- PASS: TestTraverse/Test_case_5_-_key_found_in_struct (0.00s)\n    --- PASS: TestTraverse/Test_case_6_-_key_not_found_in_struct (0.00s)\n    --- PASS: TestTraverse/Test_case_7_-_duplicate_key_found_in_map (0.00s)\nPASS\nok      github.com/egibs/deepwalk/v2/pkg/traverse       0.002s\n```\n\n## Benchmarks\nRun the included benchmarks by running `make bench`:\n```sh\n❯ make bench\ngo test ./... -bench=. -benchmem\n?       github.com/egibs/deepwalk/v2    [no test files]\n?       github.com/egibs/deepwalk/v2/cmd        [no test files]\n?       github.com/egibs/deepwalk/v2/internal/util      [no test files]\ngoos: linux\ngoarch: amd64\npkg: github.com/egibs/deepwalk/v2/pkg/traverse\ncpu: 12th Gen Intel(R) Core(TM) i9-12900K\nBenchmarkTraverse-24             1000000              1020 ns/op             764 B/op         28 allocs/op\nBenchmarkTraverseSuccess-24         7668            156473 ns/op           27399 B/op       1525 allocs/op\nBenchmarkTraverseDefault-24          706           1739258 ns/op          297695 B/op      16732 allocs/op\nPASS\nok      github.com/egibs/deepwalk/v2/pkg/traverse       3.652s\n```\n\n## Miscellaneous\n\n### Manually cutting a release\n\nTo cut a release for this package, do the following:\n- Update the `VERSION` file\n  - For now this is aesthetic but offers an easy way to reference the version outside of GitHub\n- Update `CHANGELOG.md` with a new entry matching the new version\n- Commit and push any changes to `main` (either directly or via  PR)\n- Run `git tag vX.Y.Z`\n- Run `git push origin --tags`\n- Create a new release using the new tag\n\n### Dockerfile Scan\n\n0 CVEs c/o Wolfi:\n```\n❯ grype deepwalk:latest\n ✔ Vulnerability DB                [no update available]\n ✔ Loaded image                                                                                                                      deepwalk:latest\n ✔ Parsed image                                                              sha256:15776b55889a5e6500937a6ee1d9c8b0c5f6dea8f2e9631e324f27fa48a7077c\n ✔ Cataloged contents                                                               a89b0db2a340569633d593f81c58297e103de4b8ca80f97459ed5678809c4f24\n   ├── ✔ Packages                        [14 packages]\n   ├── ✔ File digests                    [397 files]\n   ├── ✔ File metadata                   [397 locations]\n   └── ✔ Executables                     [1 executables]\n ✔ Scanned for vulnerabilities     [0 vulnerability matches]\n   ├── by severity: 0 critical, 0 high, 0 medium, 0 low, 0 negligible\n   └── by status:   0 fixed, 0 not-fixed, 0 ignored\nNo vulnerabilities found\n```\n\n## Acknowledgements\n\n[wk8](https://github.com/wk8) for their extremely handy [go-ordered-map](https://pkg.go.dev/github.com/wk8/go-ordered-map/v2@v2.1.8) package\n  - It is easy to take `collections.OrderedDict` for granted in Python and this was extremely easy to implement\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fegibs%2Fdeepwalk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fegibs%2Fdeepwalk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fegibs%2Fdeepwalk/lists"}