Why jsongrep?
JSON documents are trees: objects and arrays branch into nested values, with
edges labeled by field names or array indices. jsongrep lets you describe
sets of paths through this tree using regular expression operators—the same
way you'd match patterns in text.
**.name # Kleene star: match "name" at any depth
users[*].email # Wildcard: all emails in the users array
(error|warn).* # Disjunction: any field under "error" or "warn"
This is different from tools like jq, which use an imperative filter pipeline.
With jsongrep, you declare what paths to match, not how to traverse. The
query compiles to a
DFA that
processes the document efficiently.
Quick Example
# Extract all names from nested JSON
|
[
# Query a file directly
[
Installation
The jg binary will be installed to ~/.cargo/bin.
CLI Usage
Usage: jg [OPTIONS] [QUERY] [FILE] [COMMAND]
Arguments:
[QUERY] Query string (e.g., "**.name")
[FILE] Optional path to JSON file. If omitted, reads from STDIN
Options:
--compact Do not pretty-print the JSON output
--count Display count of number of matches
--depth Display depth of the input document
-n, --no-display Do not display matched JSON values
-h, --help Print help
-V, --version Print version
Commands:
generate Generate shell completions or man pages
More CLI Examples
Pipe from curl:
|
Count matches without displaying them:
# Found matches: 42
Query Syntax
Queries are regular expressions over paths. If you know regex, this will feel familiar:
| Operator | Example | Description |
|---|---|---|
| Sequence | foo.bar.baz |
Concatenation: match path foo → bar → baz |
| Disjunction | foo | bar |
Union: match either foo or bar |
| Kleene star | ** |
Match zero or more field/index accesses (any path) |
| Repetition | foo* |
Repeat the preceding step zero or more times |
| Wildcards | * or [*] |
Match any single field or array index |
| Optional | foo?.bar |
Continue only if foo exists |
| Field access | foo or "foo bar" |
Match a specific field (quote if spaces) |
| Array index | [0] or [1:3] |
Match specific index or slice |
The query engine compiles expressions to an
NFA, then
determinizes to a
DFA for
execution. See the grammar directory and the
query module for implementation details.
Experimental: The grammar supports
/regex/syntax for matching field names by pattern, but this is not yet fully implemented. Determinizing overlapping regexes (e.g.,/a/vs/aab/) requires subset construction across multiple patterns—planned but not complete.
Library Usage
Add to your Cargo.toml:
[]
= "0.3"
Build queries programmatically:
use QueryBuilder;
// Construct the query "foo[0].bar.*.baz"
let query = new
.field
.index
.field
.field_wildcard
.field
.build;
More examples in the examples directory.
Shell Completions
Generate completions with jg generate shell <SHELL>:
# Bash
# Zsh
# Fish
Man Page
Contributing
See CONTRIBUTING.md.
License
MIT - see LICENSE.md.