# JSON viewer

A React component in [Beamline](https://beamline.io/)'s [Data & tables](https://beamline.io/components/data) category. Live demo: https://beamline.io/components/json-viewer

A JSON value as a tree you can read and walk: branches open and close (one level, or all at once), closed ones preview what they hold, every value reads by its type, search marks and opens its way to each match, any row copies its path or its value, and values that change light once; only the rows in view are drawn.

## Use it for

- Structured data people inspect: an API response, a webhook payload, an event's properties, a tool call's arguments, a config.
- Large or deep payloads where people search for a key and copy its path.

## Not for

- Showing code or a short snippet as text ([code-block](https://beamline.io/components/code-block)).
- Folders and records people navigate ([tree-view](https://beamline.io/components/tree-view)).
- Editing JSON (a code editor).
- Two versions of a value compared ([json-diff-viewer](https://beamline.io/components/json-diff-viewer)).

## Anatomy

- toolbar: search with match count and previous / next, Expand all, Collapse all, Copy JSON
- row: depth guides, twisty, key (or index), value by type, or a closed branch's preview ({ 4 keys } / [ 12 items ] with its first entries)
- row actions arriving with attention: Copy path, Copy value
- status line: the focused row's path

## Variants

- **0**: defaultExpandDepth (1 by default; Infinity opens everything)
- **1**: rootName: what the path starts with ($ by default)
- **2**: search on or off; copy on or off
- **3**: height: px, fill, or the content's own (up to maxHeight)

## States

- empty object or array ({} and [] read as such)
- null (the hatched null mark, read as “null”)
- searching: matches marked, their branches opened, current match outlined
- no matches
- value changed since the last render (lit once)
- focused row (its path in the status line)

## Keyboard

- The tree is one tab stop; ↑ ↓ move, → opens a branch or enters it, ← closes it or goes to its parent, Home / End
- * opens every branch beside the focused one; Enter opens or closes a branch, or selects a value (onSelect)
- c copies the focused value, p its path
- / focuses search; Enter and Shift+Enter step through matches; Escape clears
- Tab reaches row copy buttons; Enter activates the focused copy button without changing the tree’s expansion or selection.

## Motion

A branch's twisty turns and its children arrive with a short fade; closing removes them at once. The focus row's tint travels between rows. A changed value lights in the accent tint and fades over three standard durations. Search opening a far branch scrolls to it (instant under reduced motion). Nothing runs at rest.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `data` (required) | `unknown` | — | Any JSON value (objects, arrays, strings, numbers, booleans, null). |
| `expanded / defaultExpanded / onExpandedChange` | `string[]` | — | Open branches by path; defaultExpandDepth decides the first ones when left out. |
| `defaultExpandDepth` | `number` | — | Levels open at first. Default 1. |
| `query / defaultQuery / onQueryChange` | `string` | — | The search; matches keys and values. |
| `rootName` | `string` | — | What paths start with. Default "$". |
| `search` | `boolean` | — | Show the toolbar's search. Default true. |
| `copy` | `boolean` | — | Copy path and value on rows, Copy JSON in the toolbar. Default true. |
| `onSelect` | `(path: string, value: unknown) => void` | — | Enter or click on a value. |
| `height` | `number \| "fill"` | — | A fixed height, or the container's; otherwise the content's own up to maxHeight. |
| `maxHeight` | `number` | — | Default 480. |
| `aria-label` (required) | `string` | — | The value's name: "Webhook payload". |
| `className / classNames / style / ref` | `string / JsonViewerClassNames / CSSProperties / Ref<HTMLDivElement>` | — | The root and its parts (toolbar, tree, row, key, value, preview, path). |

## Dependencies

`@tanstack/react-virtual`, `lucide-react`

## Import

```tsx
import { JsonViewer } from "@/components/json-viewer/json-viewer";
```

## Get it

JSON viewer is part of Beamline: 200+ components and 50+ complete screens for React that your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 launch price, one payment, no subscription, lifetime updates, one licence for your whole team. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in Data & tables

- [Event calendar](https://beamline.io/components/event-calendar): A schedule of events by day, week or month: events that overlap sit side by side, drag one to another time or day or pull its bottom edge to change its…
- [Kanban board](https://beamline.io/components/kanban-board): Work as cards in columns by stage: drag a card (or lift it with Space and walk it with the arrows) to another column or place, the cards around it make…
- [Data grid](https://beamline.io/components/data-grid): Virtualised grid for thousands of rows: multi-sort, search and value filters, resizable and pinnable columns, range selection, inline edit, footer…
- [Pivot table](https://beamline.io/components/pivot-table): Records summed up by the fields people choose: rows grouped by one or more fields that fold open level by level, columns split by another, one or more…
- [Query builder](https://beamline.io/components/query-builder): Conditions people build by hand to pick out records: each rule is a field, an operator that fits the field (contains, between, in the last N days, is any…
- [Log viewer](https://beamline.io/components/log-viewer): Log lines as they stream: it follows the newest line until you scroll up, then counts what arrived and brings you back in one click; filter by level with…
- [JSON diff viewer](https://beamline.io/components/json-diff-viewer): Two versions of a JSON value compared as one tree: added keys marked +, removed ones struck through with −, changed values read old → new, unchanged keys…
- [Import mapping](https://beamline.io/components/import-mapping): Map the columns of a file to the fields of one record type, see what every value becomes, then run the import and get an outcome for each row…
- [Diff table](https://beamline.io/components/diff-table): Proposed edits to a table before they happen: new rows green, removals struck through, changed cells old → new; each change can be left out and Apply…
- [Filter toolbar](https://beamline.io/components/filter-toolbar): The filters on a list kept in view: chips that remove themselves, Add filter with fields and their values, Clear all, and room for search or view controls.
- [Table](https://beamline.io/components/table): A plain, styled HTML table for small static data: header, body, footer, caption, numeric cells, three densities and a sticky header.
