jql
The jql jackal logo

jql

A fast, lightweight command-line tool to query JSON.
Pronounce it jackal.

Get started The grammar GitHub
⚡

Fast by construction

Queries run against a simd-json tape, so only the part of the document you select is ever built.

ðŸŠķ

One small binary

No runtime, no configuration, no plugins. Install it and pipe JSON through it.

ðŸŽŊ

A grammar, not a language

Twelve tokens that compose. No expressions, no arithmetic, nothing to learn twice.

ðŸ’Ą

Errors that say why

A failed selection names the token and shows the value it was applied to.

Start

Getting started

A query is a sequence of tokens read left to right. Each token narrows what came before it, so a query describes a path through the document.

Keys are always double-quoted, because any string is a valid JSON key — including .valid, the empty string, and a lone quote. That means a query needs single quotes in a shell, so the double quotes survive.

echo '{ "name": "jql" }' | jql '"name"'

Read a file by passing it after the query, or pipe into it:

jql '"name"' package.json
cat package.json | jql '"name"'
Tip

Wrap the whole query in single quotes. Without them your shell eats the double quotes around each key, and the query will not parse.


Reference

The grammar

Every token, with an example you can paste into a shell. Each output below was produced by running against the input beside it.

Object keys

The key selector is the one you will use most. Write selectors next to each other to walk down the document.

Arrays

Arrays are addressed by index or by range. Both accept several values, in any order you like.

Objects

Objects can be addressed by name, and also by position — useful when you know the shape but not the keys.

Operators

Four operators reshape what a selector returned rather than descending into it.

Note

The keys operator returns keys sorted alphabetically, not in document order, and the truncate operator may appear only once, as the final token of a query.

Pipes

A pipe applies the tokens that follow to every element of an array, then optionally collapses the result back to a single value.

Lenses

A lens filters an array, keeping the elements that match. It is the only token that removes elements rather than selecting them.

Groups

A comma splits a query into sub-queries, each run against the same input, collected into an array.

Putting it together

Real queries chain these pieces, and reading one from left to right tells you the whole pipeline. Every example below runs against this document:


Using it

Many documents

Input may hold more than one JSON document. Each is evaluated on its own and produces its own result.

Note

Anything trailing that is not itself a document is an error rather than being ignored, so a truncated stream fails loudly instead of returning partial results.

Flags

Eight flags, all short. The full list is in jql --help.

FlagWhat it does
-i, --inlinePrint the output on one line instead of pretty-printing it.
-q, --query <FILE>Read the query from a file rather than the command line.
-r, --raw-stringPrint a string result without its surrounding quotes.
-S, --sort-keysSort the keys of every object recursively, like jq -S.
-s, --streamProcess input line by line as it arrives, one document per line.
-v, --validateIgnore the query and report whether the input is valid JSON.
-h, --helpPrint help, including the whole grammar.
-V, --versionPrint the version.

Shell integration

jql eats JSON and writes JSON back, so it composes with everything else in a pipeline.

Save the output

jql '"repos"' input.json > output.json

Assign a value to a variable

Combine --raw-string with --inline so the result arrives without quotes or newlines:

name=$(jql -r -i '"name"' package.json)

Keep the query in a file

Long queries are easier to read, and to version, when they live on disk:

jql --query ./select-repos.jql input.json

Follow a stream

Without --stream the whole input is read before anything is written, which is right for a file or a finished pipe. With it, each line is processed as it arrives — for output still being produced:

docker logs --follow my-container | jql --stream '"message"'

It expects one document per line. A document spread over several lines needs the default mode.

Check exit codes

jql --validate input.json && echo "valid"

Installation

Packaged for most platforms, or grab a prebuilt binary.

PlatformCommand
Cargocargo install jql
Cargo Binstallcargo binstall jql
Alpine Linuxapk add jql
Arch Linuxyay -S jql
Fedoradnf install jql
FreeBSDpkg install jql
Homebrewbrew install jql
Nixnix-env -i jql
openSUSEzypper install jql

Prebuilt binaries for Linux, macOS and Windows are attached to every release.

Good to know

Errors say what went wrong

A failed selection reports the token that failed and the value it was applied to, rather than returning null and leaving you to guess.

It is not jq

There is no plan to align jql with jq or any similar tool. jql selects and reshapes; it has no expression language, no arithmetic and no user-defined functions, and that is deliberate.

Speed

Selection queries run against a simd-json tape, so only the part of the document a query actually selects is ever built. Measurements against jq live in PERFORMANCE.md.

Caveat

Two JSON parsers are in play, and they round the last bit of some scientific-notation literals differently, by up to two ULP. The tape returns the correctly rounded value. Plain decimals, integers and strings are unaffected.