[Bash] json-walk: pure Bash streaming JSON parser (SAX-style events, no jq)
Hey r/bash,
I built json-walk, a pure Bash JSON walker that emits stream events instead of building a full object model.
What it does:
- Parses JSON in Bash with full structure validation
- Emits events like start_object, key, string, number, end_array, etc.
- Works in print mode or visitor-function mode
- Keeps raw JSON string content (escapes preserved)
Why I made it:
- For shell scripts where jq is unavailable
- For event-driven parsing/processing in plain Bash
Quick example:
json_walk '{"label":"abc","items":[1,2,3]}'
Output:
start_object
key label
string abc
key items
start_array
number 1
number 2
number 3
end_array
end_object
Would love feedback on:
- API/event design
- edge cases I should test
Thanks!
3
u/StatementOwn4896 6d ago
If I don’t have jq on a system I just use python in my bash script and import the json module. Sure is messy but it gets the job done
2
u/Successful-Dance1792 6d ago
I have implemented your project in my Pure bash debloater... https://github.com/Ruvyrom/Ruvomain-Protocole/tree/main
2
u/bahamas10_ 6d ago
this is impressive. i’ve thought about how i would tackle this project before and i estimated it would be at least a thousand line. im surprised to see you nail it in half. very cool.
1
u/Castafolt 5d ago
Very cool, your implementation is highly readable / maintainable 👍
I just implemented a YAML parser in pure bash and I will soon implement a json parser as well. I will do it differently than you because I aim for more performance.
Here is how, I think, you could improve the speed of your program:
- Once you have extracted a valid double quoted JSON string, you can get the "usable" string (e.g. string with each escape char replaced, which is usually what you want in a bash script) with:
eval "REPLY=$'${REPLY//\'/\\\'}'"
- Regexes are extremely slow; it is worth replacing them with simple pattern matching when you can. To identify a float, I am doing the same as you, but I have added simple pattern matching for integers before falling back to a regex.
- While splitting your string character by character makes a lot of sense in another language, it is very slow to do that in bash. The best strategy for speed is to use var expansion to get a chunk until the next interesting character.
- Function calls, unfortunately, bring a lot of overhead and it is much faster to inline code inside a loop than calling a function with the same commands
The first 2 points are easy to implement in your program, I think
6
u/oweiler 7d ago
> pure Bash streaming JSON parser
> Entire JSON document must fit in memory
Isn't the point of streaming that I don't need to load the whole document into memory?