zjson
Parse, validate, query, and quote JSON in pure Zsh. zjson works with native scalars, arrays, and associative arrays without invoking jq, Python, or another executable.
Initial development release: zjson 0.1.0 extracts the JSON core from zcoder.zsh behind a new API that may evolve.
JSON Without Leaving the Shell
Pure Zsh
Parse and encode JSON with Zsh builtins and parameter expansion. No jq, Python, external commands, third-party modules, or build step.
Native result values
Decode objects into associative arrays, arrays into indexed arrays, and scalar types into regular Zsh variables.
JSON Pointer lookup
Resolve RFC 6901 pointers into nested objects and arrays, including escaped key characters, empty keys, and typed null values.
Exact scalar handling
Keep number spelling and distinguish strings from booleans and null while decoding escapes into UTF-8.
Structured diagnostics
Inspect stable error codes plus 1-based byte offsets, line numbers, and locale-consistent columns for malformed input.
Tokenizer access
Validate, discard, or capture values from streaming token calls, with context helpers for nested operations.
Source It and Parse
Keep zjson.zsh beside its lib directory, source the entry point, and call functions directly. Results stay in the current shell; check the return status before reading output variables.
source /path/to/zjson/zjson.zsh
if zjson_parse_object '{"name":"zjson","enabled":true,"ports":[8080,8081]}'; then
print -r -- "${ZJSON_OBJECT[name]}"
print -r -- "${ZJSON_OBJECT_TYPES[enabled]}"
zjson_parse_array "${ZJSON_OBJECT[ports]}"
print -rl -- "${ZJSON_ARRAY[@]}"
else
print -u2 -r -- "$ZJSON_ERROR"
fiWhole-document functions publish results only after complete validation succeeds. A new call replaces the documented ZJSON result variables.
Navigate Nested JSON
Use JSON Pointer when a script needs one value rather than a complete decoded container. Pointer indexes start at zero, while native ZJSON_ARRAY indexing starts at one.
json='{"servers":[{"host":"localhost","port":8080}],"token":null}'
if zjson_get "$json" /servers/0/host; then
print -r -- "$REPLY ($ZJSON_TYPE)"
fi
zjson_get "$json" /token
print -r -- "$REPLY ($ZJSON_TYPE)"Lookup reports malformed JSON separately from a valid pointer that cannot resolve. It also detects ambiguous duplicate members while allowing duplicates elsewhere in the document.
Encoding, Diagnostics, and Context
zjson_quote encodes strings with JSON control-character escaping, while zjson_utf8_repair replaces malformed UTF-8 prefixes with U+FFFD. String encoding is intended for text, not lossless binary transport.
Token functions expose punctuation, scalar types, decoded values, and byte offsets for callers that need incremental control. zjson_with_context restores the outer tokenizer and diagnostics around nested operations.
Compatibility and Limits
Zsh 5.8 and newer are supported. The release matrix covers Zsh 5.8 and 5.9.2 on Linux in both C and C.UTF-8 locales with the command path empty.
Input must be UTF-8 without a leading BOM. Nesting is limited to 128 levels, parsing holds the complete source in memory, and there is one shared tokenizer rather than independent parser objects. The library is intended for shell-sized JSON documents, not streaming large datasets.