fastgron flattens JSON into greppable assignments without changing the values
High-performance JSON to GRON (greppable, flattened JSON) converter
At a glance
- What is it?
- fastgron is a C++20 converter that rewrites JSON as flat path assignments so a shell pipeline can grep it, and it converts back with --ungron. It is aimed at engineers poking at large API responses on a terminal, and it is far less useful for reading JSON in a structured way.
- Who is it for?
- Engineers who need to find one field in a huge API response from a terminal, and pipeline authors who want grep on JSON without writing a jq program, are the people fastgron serves well. It is the wrong tool for structured querying, for input that is not valid JSON in the first place, and for Windows users who need to read a URL directly, since the released Windows binary has no libcurl support.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 111 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Turning nested JSON into a list of paths you can grep
JSON is easy to parse and hard to search with ordinary tools. A grep for a key name returns a whole line of dense JSON, and a nested value sits in the middle of that line with no obvious anchor. fastgron solves this by rewriting the document as discrete assignments, one per leaf value, where each line carries the absolute path to that value. The stated motivation is easing the exploration of APIs that return large blobs of JSON but have terrible documentation. The output looks like assignment statements rather than JSON, which means every tool in a shell pipeline can treat it as text. That is the whole trick. Nothing is lost in the flattening, because the same tool walks the assignments back into JSON, so a filtered result can be reconstituted rather than being a dead end. The audience is narrow and specific: engineers at a terminal who need to find one field in a large response, and script authors who want plain grep semantics over structured data.
The C++20 and simdjson core is what makes the difference
The implementation is written in C++20 and uses the simdjson library, which is where the speed claim comes from. The README states a 50x speedup over gron on big files, with 400MB/s input and 1.8GB/s output on an M1 MacBook Pro, and a separate measurement on a 190MB file. Gron, the original tool this project replaces, is a separate implementation, and that is the fundamental difference in approach rather than a matter of tuning. A separate implementation has to build and print its representation one line at a time through a text pipeline, while a native binary with a SIMD accelerated JSON parser walks the document directly. The output ordering is also different by default, since fastgron does not sort unless asked, which is why the timing comparison runs both with and without --sort and the sorted case still finishes well ahead. The build needs a C++20 compatible compiler, CMake 3.8 or higher, and libcurl if you want URL support.
Running fastgron for the first time on a local file
The quickest way to see the format is to convert a small file that ships in the repository. The example file is named two.json, and running the converter on it prints one assignment per value, including the array elements with their indices and the nested object as its own empty assignment. The two blocks below show the file and the converted form side by side, which is the clearest single illustration of what the tool does. You can also leave the filename off entirely, or pass a dash, and the data is read from standard input, which is how fastgron slots into a pipeline.
$ cat testdata/two.json
{
"name": "Tom",
"github": "https://github.com/tomnomnom/",
"likes": ["code", "cheese", "meat"],
"contact": {
"email": "[email protected]",
"twitter": "@TomNomNom"
}
}$ fastgron testdata/two.json
json = {}
json.name = "Tom"
json.github = "https://github.com/tomnomnom/"
json.likes = []
json.likes[0] = "code"
json.likes[1] = "cheese"
json.likes[2] = "meat"
json.contact = {}
json.contact.email = "[email protected]"
json.contact.twitter = "@TomNomNom"Reading a URL directly, and the Windows curl gap
Because libcurl is an optional dependency, fastgron can take a URL in place of a file name, and the README demonstrates it against the GitHub commits API, piping the flattened output straight into fgrep. That pipeline is the intended usage: a remote endpoint in, a narrow filter in the middle, and the whole thing on one line of shell. The wrinkle is platform coverage. The Quick Install section notes that the released Windows binary is missing libcurl support, so http and https URLs cannot yet be read directly there, and Linux and macOS users are told to download the latest binary from the releases page, while Arch, Homebrew and Nix users install through their package managers. The build from source is the escape hatch for anyone who needs the curl feature on Windows, since libcurl is listed as an optional build requirement.
Going back to JSON with --ungron after a grep
The reverse conversion is what turns fastgron from a viewer into a pipeline stage. Run the converter, filter the flattened output with a normal text tool, and feed the surviving lines back through the same binary with --ungron, and you get a valid JSON document containing only the fields that matched. The README shows the round trip on the GitHub commits response, where filtering on the author path and ungronning produces a small array with the commit, author, date, email and name fields intact. This matters on large inputs, where the difference is stark: the README reports that gron was killed while converting an 800MB file back to JSON, whereas fastgron finished the same kind of conversion in 8 seconds. Reconstruction is not lossy for a filtered subset, and that makes the tool usable in a data pipeline rather than only in an interactive session.
Path filtering, the -p accessor syntax and its limits
Beyond grep, fastgron has its own path language, and this is where the tool either earns its place or does not. The -p option takes a path such as .#.3.population or cities.#.population, where the hash stands in for an array index, and more complex expressions are possible, including a brace list of keys and a slice form such as users[1:-3:2].{name,address}. There is also a double bracket form that acts as an index accessor without emitting anything on the path, and a renaming form such as {globalid:id,user:users:[[1]],...} that maps a value onto a different key. The help text is candid about the last of these, calling path renaming a minimal, limited implementation right now, and that caveat is worth taking at face value. The README also reports that path finding is 18x faster than jq and 5x faster than jj on a large file, with the measured times listed for all three. If your query needs a projection or a rename, verify those forms against your own data before building on them.
Where fastgron is the wrong tool
fastgron is a text-shaped view of JSON, and it inherits the limits of that view. It cannot answer questions that need the structure preserved, such as counting keys that match a pattern across a document or transforming values in place, because the flattened form is designed for matching fixed strings, not for computation over the tree. The built-in filter flags are correspondingly narrow: -F matches a fixed string, -v inverts that match, -i ignores case, and --sort orders output by key. Anything beyond that is the job of another tool. A second, sharper limit is platform support for remote data, since the Windows release cannot read a URL at all, which pushes Windows users toward local files or a source build. A third is input validity. The tool converts JSON, and a stream of malformed or non-JSON lines is not something it repairs.
Output control flags and stream mode for JSON lines
The remaining options are mostly about making the output fit a script. --root changes the root path, which defaults to json, so an assignment can start from a name of your choosing. --no-indent and --no-spaces control the spacing around the equals sign, --semicolon appends a semicolon to each line for languages that want one, and -c or --color colorizes the output with --no-color to turn it off. For input, the -s or --stream flag switches on stream mode, which is meant for JSON lines, one document per line, and the shape of the output changes to match: the root becomes an array and each line's document is indexed under it. The --user-agent and --header options set the HTTP user agent and custom request headers, which matters when an endpoint is picky or rate limited. The project itself is MIT licensed, so the binary and any derived code can be redistributed without a fee, and the repository is not archived, with the last push on 2026-07-04.
Editorial conclusion
Engineers who need to find one field in a huge API response from a terminal, and pipeline authors who want grep on JSON without writing a jq program, are the people fastgron serves well. It is the wrong tool for structured querying, for input that is not valid JSON in the first place, and for Windows users who need to read a URL directly, since the released Windows binary has no libcurl support. Check three things before adopting it: the path syntax you actually need, because the accessor and renaming forms are described as a minimal, limited implementation; the release channel, since the newest tag is v0.7.7 from 2023-12-06 while the last push was on 2026-07-04; and the licence, which is MIT, so redistribution of the binary or a fork carries no fee.
Frequently asked questions
How do I install fastgron?
Arch users install with yay -S fastgron-git, Homebrew users with brew install fastgron --build-from-source, and Nix users with nix profile install github:adamritter/fastgron#fastgron. For Ubuntu and Windows, the README points to the latest binary on the releases page.
How do I convert a filtered fastgron output back into JSON?
Pipe the filtered output into the same binary with the -u or --ungron option, for example fastgron "https://api.github.com/repos/adamritter/fastgron/commits?per_page=1" | fgrep commit.author | fastgron --ungron. The result is a JSON document containing only the fields that survived the filter.
Why can fastgron not read a URL on Windows?
The README states that libcurl support is missing from the released Windows binary, so http and https URLs cannot be read directly there. Building from source with libcurl installed is the documented way to get URL support.
What is the difference between fastgron and gron?
fastgron is a C++20 program built on simdjson, while gron is a separate implementation, and the README reports a 50x speedup on large files. The output format follows the same idea, and fastgron can also convert back to JSON where gron was killed on an 800MB file.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/adamritter-fastgron)Was this useful?