Skip to content

About

πŸ” A fast, native desktop GUI for browsing and querying large JSON files β€” supports jq, JSONPath, JMESPath, and JSON Pointer. Built in Rust.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

61 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

jsonquery gui

A native desktop tool for browsing and querying large JSON files β€” drag in a file (or paste JSON directly) and query it with jq, JSON Pointer, JSONPath, or JMESPath. A Tools window merges, formats, diffs, patches and validates documents too. Built in Rust with egui/eframe.

jsonquery: a multi-line jq query that filters, groups and reshapes a list of users, every step of it tinted, with the source and the results side by side

Features

  • Four query dialects, one box β€” jq (via embedded jaq), JSON Pointer (RFC 6901), JSONPath (RFC 9535), and JMESPath. Pick one from the toolbar or let the app auto-detect it from what you type.

  • Inline autocomplete β€” as-you-type suggestions for each dialect's built-in functions (with a short doc string) and for the loaded document's own keys and array indices β€” type . or [ to see what's there, with a sample value next to each key. In jq it follows pipes and calls too: inside .[] | select(. it offers the fields of each record. Accepted text is spelled for the dialect (.["first name"] in jq, $["first name"] in JSONPath, ."first name" in JMESPath). Off by default β€” switch it on with the πŸ’‘ button in the toolbar.

    Autocomplete inside select( offering the fields of each record, with a sample value for each

  • Colour-coded queries β€” the query box tints each step of what you type (.[], select(…), sort_by(…), .user.name; a Pointer's /segments) in the same palette the tutorial uses, leaving pipes, commas and operators plain, so a long query's structure is visible at a glance β€” see the query at the top of this page. A call inside a call gets its own tint, the colours follow the selected dialect, and half-typed queries are fine.

  • Built-in tutorial β€” the πŸ“– icon in the toolbar (or F1) opens a separate window with a lesson tree for each dialect. Every lesson has short examples with the query broken down piece by piece and a live result; β–Ά Try it loads an example's data and query into the main window so you can edit and experiment. See Tutorial.

    The tutorial window on the jq lesson about select

  • Tools β€” the πŸ›  icon next to the tutorial opens the Tools window, with a tab for each of five utilities that go with the viewer: Merge JSON, Format JSON, Diff JSON, Patch JSON and Validate Schema. Each is shown in action under Tools below. They open in a window of their own, or docked in the main window β€” the βš“ button in their row of tabs gives the main window a row of tabs: Json Query itself, then the five tools.

  • Streamed, cancellable queries β€” results appear as jq produces them, so first(...)/limit(...) genuinely stop early; starting a new query aborts whatever was still running.

  • Exact number round-tripping β€” big integers (snowflake IDs, Postgres bigints) survive a query byte-for-byte instead of quietly rounding through an f64.

  • NDJSON support β€” one JSON value per line loads as a single queryable document, no separate format to pick.

  • Tree or raw text views β€” toggle either the source document or the query results between a virtualized, expand/collapse tree and plain, selectable/copyable pretty-printed text.

  • CSV and TSV out β€” end a jq query with @csv or @tsv, for example .[] | [.name, .age] | @csv, and the results are rows of text: Copy to Clipboard, Save… and the Text view write them as CSV or TSV, a line per result, not as quoted JSON strings. A CSV/TSV note beside the Tree and Text buttons says when that applies. (jaq has neither filter; jsonquery adds them, with IN, INDEX, JOIN, tostream, fromstream and truncate_stream.) The tutorial teaches them on the pages of its Tables & lookups and Event streams topics. Below, the Text view of an @csv query, and the file Save… wrote from it, open beside the window in a spreadsheet; end the query in @tsv and the rows are tab-separated.

    A jq query that ends in @csv: its rows in the Results pane's Text view, and the users.csv that Save… wrote from them, opened in a spreadsheet beside the window

  • Search β€” Ctrl+F opens a Notepad++-style Find dialog with the cursor already in its field: a case-insensitive substring or regex search across the source or the results tree. Find (or Enter) jumps to each match in turn β€” expanded, scrolled to and highlighted β€” with a running "2 of 3", wrapping past the last one; Find All lists every match in a panel below, where a click reveals it.

    The Find dialog and its Find All list, with the selected match revealed in the source tree

  • Find in Source β€” right-click a result row to see where it came from. The row's key and value are matched against the source, and for array elements their position: one hit is revealed directly, several are listed with the best guess selected, and a computed value falls back to a text search.

  • Right-click row menus β€” copy a node's path or its JSON to the clipboard, search from that scope, save just that node to a file, or expand a whole subtree at once.

  • Save to file β€” the whole source document, the whole result set, or a single node, independently.

  • Load however's convenient β€” drag-and-drop (several files at once are offered to Merge JSON), a Source field that takes a URL or a local path (type it or paste it, or browse with …), or pasting JSON straight into the text area.

  • Resizable query box that scrolls β€” drag the query panel's bottom edge to make it any height; a long query scrolls inside it (the cursor stays in view) instead of taking over the window.

  • Pop-out panes β€” the Query, Source and Results panes each have a small ⬈ icon in the top right corner of their header that opens the pane in a window of its own β€” a big query on a second monitor, or the results beside a full-height source. The main window gives the room to whatever is left. The ⬋ icon in that window, or just closing it, docks the pane back, and a πŸ—– button in the toolbar (there while anything is out) brings every window back at once. The Source pane's window has a Source field of its own on top (with …, Load and Clear), so a document can be opened from there. Shortcuts and search work in each window.

    The Results pane popped out into a window of its own; the main window gives the Source pane the full width

  • Light and dark themes, switchable from the toolbar.

  • Settings and a memory β€” the βš™ at the right end of the status bar opens a small window with the limit on file sizes that matters: from what size a file is memory-mapped and kept on disk instead of being loaded. Under Advanced are the others: how much the Tools window takes, how big a download or a copy may be, how much a query on a huge file may hold. Hover a name for what it does and its default, which is what the app has always used. The app also starts as you left it: the theme, whether autocomplete is on, the size of the window (maximized or not) and of its panes, and whether the Tools are docked. All of it is in one small file, ~/.jsonquery/settings.json. See docs/settings.md.

  • On the web β€” the 🌐 in the status bar, between the β“˜ and the βš™, opens jsonquery.dev in your web browser: this app's query engine in a browser tab, with nothing to install β€” jq, JSONPath, JMESPath and JSON Pointer queries, the five tools, and short lessons for each language. The β“˜ window links to the site too. The app never contacts the site by itself: the 🌐 only hands the address to your browser when you click it.

  • Keyboard shortcuts β€” Ctrl+Enter run/apply, Ctrl+F search, Ctrl+S save (both scoped to whichever panel you last clicked), F1 tutorial.

Tools

The πŸ›  icon in the toolbar opens the Tools window: five small utilities, each on a tab of its own, laid out like the main window β€” a command row with the tool's main button and its options, what goes in on the left, what came out on the right, and a status bar that says what happened. JSON goes into a box by pasting, by dropping a file on the window, with Open file…, or with Open document (the one in the main window). A result can be copied, saved, or opened in the main window as a document of its own, to query like any other. Ctrl+Enter runs the tab's main button and Cancel stops a job. The tools work in memory, so they are for documents that are not very large (what a run is given may add up to 128 MB, which is a setting). Details in docs/tools.md.

The Tools can also be docked into the main window, so that the whole app is one window: the βš“ button at the right end of their row of tabs gives the main window a row of tabs β€” Json Query first, which is the window as it has always been (the source field, the query, Source and Results), then one tab for each tool β€” and what the tab in front holds takes the window. The theme and the tutorial stay at the right end of the row; the πŸ—— at the bottom right, in the status bar beside the βš™, undocks the Tools into a window of their own again. Ctrl+Enter and a file dropped on the window go to what is in front: a tool's tab runs and takes the file in one of its boxes, Json Query runs the query and opens the file as the document (several files go to Merge, whose tab comes to the front). Where the Tools are is remembered.

The Tools docked in the main window: the row of tabs with Json Query first, and Diff JSON in front

Merge JSON

Combines several files into one document with a jq filter, the way jq -s does: the files are read in the order listed and slurped into one array, which is the filter's input, and $files holds their names. Drop the files on the window (or several at once on the main window), or press Add files…; pick a ready-made filter from Merge as β€” append arrays, append sorted and de-duplicated, deep-merge objects, bundle by file name β€” or edit it into your own, and press Merge. The result can be saved, or opened in the main window.

Merge JSON: three monthly order files appended into one array of ten orders

Deep-merge objects lays each file over the one before it, key by key all the way down: a later file wins a clash between plain values, a key that only one file has is kept, and an array is replaced as a whole. Below, a defaults.json, a production.json and a local.json become one configuration. A filter of your own can merge differently β€” docs/tools.md has one that joins the arrays too.

Merge JSON with Deep-merge objects: defaults.json, production.json and local.json laid over each other into one configuration, the nested keys merged, the later file's value winning, the array replaced

Format JSON

Pretty-prints with 2 or 4 spaces or a tab, minifies, sorts the keys at every depth, and can write everything outside ASCII as \uXXXX escapes. Numbers come out exactly as they went in, however many digits they have.

Format JSON: a minified document pretty-printed with its keys sorted

Diff JSON

Compares a Left and a Right document the way a file-comparison tool does. Side by side shows both pretty-printed, line by line: what only Left has in red, what only Right has in green, what changed in amber with the differing characters picked out. The sides scroll together, the strip at the right edge has a tick for every difference, β–²/β–Ό (Alt+Up, Alt+Down) step through them, and Differences only folds what is the same. Its tab compares the two documents by itself β€” Compare is for comparing again. Changes lists each change with its JSON Pointer, and Patch is the RFC 6902 JSON Patch that turns Left into Right β€” Copy patch or Save patch… it. Key order is not a difference, numbers are compared by value with their exact digits, and arrays are aligned by content, so an inserted element is one change rather than a change to every element after it.

Each difference has two arrows between the sides, one over the other, at its first line: press one and the document it points at takes what the other has there, as a file-comparison tool's "copy to left/right" does; the comparison runs again and the view stays where it was. Not the whole difference? Click a line to pick it (Ctrl adds one, Shift picks a run, a drag runs over several, Esc lets go): the arrows, ⏴ and ⏡ (Alt+Left, Alt+Right) and the right-click menu of a line then move only the lines picked. Either side can also be edited in place: double-click a line to put a caret in it β€” type, press Enter, and what you typed (a value, a member, nothing to take the line out, several to put them in) is in the document and compared again. A document that a move or an edit changed says so, and the Save… over its column writes it to a file β€” either, or both.

Diff JSON: two versions of a configuration side by side, with the added, removed and changed lines marked, two arrows one over the other between the sides at every difference, a line picked in the left document and, in the right one, the same line with a caret in it and a new value being typed over it

Patch JSON

Applies an RFC 6902 JSON Patch (a list of operations) or an RFC 7386 JSON Merge Patch to a document. A patch is all or nothing, and an error names the operation that failed.

Patch JSON: six operations applied to a document, the result on the right

Validate Schema

Checks a document against a JSON Schema (drafts 4, 6, 7, 2019-09 and 2020-12, read from $schema) and lists every problem with its pointer and what is wrong. For the document that is open in the main window, Show in main window reveals a problem there. Nothing is ever fetched: a $ref has to point inside the schema.

Validate Schema: a document checked against a schema, six problems listed with their pointers

Known limitations

  • Drag-and-drop doesn't work on native Wayland β€” a gap in winit (eframe's windowing library), which only implements OS-level file drop on Windows, macOS, and X11 (rust-windowing/winit#1881). The Source field (and its … file picker), the Tools window's Add files… and Open file… buttons and pasting all work fine everywhere. Workaround: run under XWayland instead, one click away once it is set up; see Dropping files on a Wayland desktop.
  • Pop-out windows open wherever the compositor puts them on native Wayland β€” winit can neither set nor read a window's position there, so a popped-out pane can't open over the spot it left or reopen where you moved it. (Windows, macOS and X11 can; only X11 has been tried β€” the XWayland entry above gets you there on a Wayland desktop.)
  • A file of 256 MiB or more is not parsed but kept on disk and read as you look at it (that size is a setting; memory-mapped, and indexed once when it opens; a download and the result of a Merge that big are kept in a temporary file the same way), so that a gigabyte of JSON takes megabytes, not the twelve to seventeen times its size that a parsed tree does. Long lists are shown in runs of a thousand; jq queries read the file as they go, so .[] | select(…) | .name, map(…), length, .[1234567], first(…), .., sort_by(…), group_by(…) and min_by(…) work on any size (a sort takes some memory for the keys, about the size of the file at the most), but a program that needs the whole of a list as a value (add on the document, to_entries, flatten) says so instead of running. JSONPath and JMESPath work the same way ($[?(@.qty > 48)].id, [?qty > `48`].id), apart from functions that need a whole big list (sort_by, max). Format in the Tools window writes such a file indented or minified without holding it; the rest of the Tools window, and Copy of more than 64 MiB (a setting too), don't work on one, and the file should stay as it is while it is open (if another program cuts it short, the app says so and refuses to answer from what is gone, rather than closing). See Scaling beyond in-memory.

Getting started

Homebrew (Linux)

brew tap nujufas/jsonquery-gui
brew install jsonquery-gui

macOS builds aren't published yet, so the tap is Linux-only for now. If Homebrew refuses the formula as an untrusted tap, run brew trust nujufas/jsonquery-gui first.

Snap (Linux)

sudo snap install jsonquery-gui

Also available on the Snap Store, for both x86-64 (amd64) and ARM (arm64) machines. The snap is sandboxed: it reads files in your home folder directly. For files on an external drive or under /mnt, run sudo snap connect jsonquery-gui:removable-media once (the … file picker works for any file without it). To drop files on its window under Wayland, see Dropping files on a Wayland desktop.

Scoop (Windows)

scoop bucket add jsonquery-gui https://github.com/nujufas/scoop-jsonquery-gui
scoop install jsonquery-gui/jsonquery-gui

This installs the release's Windows zip with a Start-menu shortcut and a jsonquery-gui command; scoop update jsonquery-gui follows new releases. The executable is not code-signed, so Windows SmartScreen may warn the first time it runs.

Download a build

Prebuilt Linux and Windows binaries are attached to each GitHub Release. An AUR package (jsonquery-gui-bin) is also available for Arch-based distros. To build the app yourself, see Build from source below.

The AppImage is desktop-pinnable out of the box: it self-registers a .desktop entry and icon on first launch (no appimaged/AppImageLauncher required), so right-click β†’ Pin works from the taskbar/dock immediately. It embeds the static type 2 runtime (no libfuse2 needed to start it), carries fallback copies of the xkbcommon libraries for systems that lack them, and embeds update information, so AppImageUpdate (or a launcher built on it) can fetch newer releases. On a Wayland desktop it also adds a jsonquery (X11) entry, for dropping files on the window (see Dropping files on a Wayland desktop).

Dropping files on a Wayland desktop

Most current Linux desktops (Ubuntu, Fedora and others) run Wayland, where jsonquery can't take a file dropped on its window (see Known limitations). Everything else works. To be able to drop files, start jsonquery under X11 instead (XWayland, which the desktop provides on request). Which one you have:

echo $XDG_SESSION_TYPE    # wayland: read on. x11: nothing to do

What you need is a jsonquery (X11) entry in your application menu, next to the regular jsonquery: click that one, and drop files on its window.

  • AppImage: nothing to do. On a Wayland desktop the AppImage adds that entry by itself the first time you start it, and again if you move it or replace it with a newer one. (AppImages made before this was added don't: use the script below.) To get rid of it, delete ~/.local/share/applications/jsonquery-gui-x11.desktop; it stays gone until you move or replace the AppImage.
  • Everything else (the tar.gz, the snap, the Arch package, an older AppImage): scripts/jsonquery-x11.sh adds the entry (and, if you ask, a shortcut on the Desktop) with one command. The tar.gz has the script inside. For the others, the program carries it: when it is running on native Wayland, a ⚠ appears at the bottom right, beside the βš™. Click it, then Download jsonquery-x11.sh, and choose where to save it; the popup then shows the command to run, with a Copy command button. Or download it yourself:
curl -fLO https://raw.githubusercontent.com/nujufas/jsonquery_gui/master/scripts/jsonquery-x11.sh
bash jsonquery-x11.sh              # add "jsonquery (X11)" to the application menu
bash jsonquery-x11.sh --desktop    # ... and put a shortcut on the Desktop too

Then press the Super key, type jsonquery, click jsonquery (X11), and drop files on its window.

  • The script finds jsonquery by itself: the program next to it, the snap, or the Arch package. If you keep an AppImage somewhere, name it (make it executable first with chmod +x): bash jsonquery-x11.sh ~/Apps/jsonquery_gui-0.5.1-x86_64.AppImage
  • Moved or updated the program? Run the script again; it rewrites the entry.
  • bash jsonquery-x11.sh run starts jsonquery under X11 once, without adding anything; remove takes the entry and the shortcut away; check says what it found. On a desktop that is not Wayland the script does nothing.
  • With no script at all, the same thing from a terminal: env -u WAYLAND_DISPLAY -u WAYLAND_SOCKET jsonquery_gui (for an AppImage, its file instead; the snap's program is /snap/bin/jsonquery-gui; from source, env -u WAYLAND_DISPLAY -u WAYLAND_SOCKET cargo run --release -p jsonquery_gui).
  • It needs XWayland. If the script says DISPLAY is not set, your desktop has it switched off: look for an XWayland or "X11 apps" setting, then log in again.

Build from source

Requires a Rust toolchain (stable).

git clone https://github.com/nujufas/jsonquery_gui.git
cd jsonquery_gui
cargo run --release -p jsonquery_gui

Usage

  1. Get JSON in: drag a file onto the window, type or paste a URL or file path into the Source field and press Load (… browses for a file), or paste JSON into the text area.
  2. Pick a query engine (or leave it on auto-detect) and write a query, e.g. .users[] | select(.active) | {name, roles} for jq, /users/0 for Pointer, $.users[*].name for JSONPath, or users[?active].name for JMESPath. New to one of them? The πŸ“– tutorial has short lessons for all four, and the πŸ’‘ autocomplete knows the document's keys.
  3. Press Run (or Ctrl+Enter). Results stream into the right-hand panel β€” toggle it between Tree and Text, search it, pop it out into its own window, or save it.
  4. To merge, format, diff, patch or validate documents instead, open the πŸ›  Tools window.

Building

Native release build for the current platform:

cargo build --release -p jsonquery_gui
# binary at target/release/jsonquery_gui

Development

cargo test --workspace     # unit tests: parsing and tree logic, the query engines and tools, headless window tests
cargo clippy --workspace --all-targets

The workspace is split into three crates so the non-GUI logic can be tested without pulling in a GUI toolkit:

  • crates/core β€” file ingest (parse, or mmap + index for a file of 256 MiB or more) and the virtualized-tree data layer.
  • crates/query β€” the four query engines, dispatched through a shared QueryEngine trait, plus the merge, format, diff, patch and schema logic behind the Tools window.
  • crates/app β€” the eframe/egui application itself.

GUI tests: jsonquery_test

The end-to-end tests live in their own repository, jsonquery_test: a Robot Framework suite that starts the real application on a virtual display of its own and drives it the way a person would. Its README says what it covers and how to run it; clone it beside this checkout (it finds the app as ../jsonquery_gui, or wherever JQ_APP_DIR points) and start with ./run.sh.

The CI workflow (ci.yml) runs fmt, clippy, the unit tests and a release build on Linux, Windows and macOS for every push and pull request. The GUI suite runs on Linux from the Actions tab (Run workflow, optionally just one suite) and every Monday; its report is kept as the gui-test-results artifact.

Architecture

The design β€” pipeline, concurrency model, crate layout β€” is written up in docs/:

License

MIT. The app has no accounts, telemetry, crash reporting or update checks of its own β€” see PRIVACY.md.

Built with the help of Claude β€” see docs/ for the architecture docs behind it.

About

πŸ” A fast, native desktop GUI for browsing and querying large JSON files β€” supports jq, JSONPath, JMESPath, and JSON Pointer. Built in Rust.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages