JSON Viewer

Collapsible, syntax-colored JSON tree with path copying, search, and expand/collapse controls. Designed for dev dashboards, API documentation, and debugging tools.

lucide-react

Preview

API Response

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

Installation

$ shadcn add https://ui.justinlevine.me/r/json-viewer.json

Usage

import { JsonViewer } from "@/components/json-viewer"
<JsonViewer data={myObject} title="Response" />

Pass any JSON-serializable value. Click the chevron to expand/collapse nodes. Hover a row and click the path icon to copy the access path (e.g. response.metadata.preferences.theme).

Examples

Expand depth

Control how deep the tree is expanded on initial render. Set defaultExpanded to a number for depth, or true for fully expanded.

Depth 1 (default)

Depth 1

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {3 items},
"teams": [2 items]
}

Fully expanded

Fully Expanded

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {
"theme": "dark",
"notifications": true,
"locale": "en-US"
}
},
"teams": [
0: {
"id": "team_01",
"name": "Engineering",
"role": "lead"
},
1: {
"id": "team_02",
"name": "Platform",
"role": "member"
}
]
}

Real-world data

package.json

package.json

6 keys
"pkg": {
"name": "@acme/dashboard",
"version": "2.4.1",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "vitest"
},
"dependencies": {
"next": "15.5.9",
"react": "19.1.0",
"react-dom": "19.1.0",
"tailwind-merge": "^3.3.1",
"lucide-react": "^0.487.0"
},
"devDependencies": {
"typescript": "^5.9.2",
"tailwindcss": "^4.1.11",
"vitest": "^3.1.0"
}
}

API list response

Search Results

3 keys
"data": {
"status": "ok",
"total": 3,
"results": [
0: {5 items},
1: {5 items},
2: {5 items}
]
}

Type coloring

Each JSON type gets a distinct color: strings (green), numbers (blue), booleans (amber), null (muted italic), and keys (violet).

All primitive types

Type Colors

10 keys
"values": {
"string_value": "hello world",
"number_int": 42,
"number_float": 3.14159,
"boolean_true": true,
"boolean_false": false,
"null_value": null,
"empty_string": "",
"zero": 0,
"negative": -17,
"long_string": "The quick brown fox jumps over the lazy dog near the riverbank at sunset."
}

Primitive root values

Works with non-object root values too — strings, numbers, booleans, and null render inline.

String

message: "hello world"

Number

count: 42

Boolean

active: true

Null

result: null

Color themes

Pass a colorTheme prop with any shiki theme name to apply editor-style coloring. All 65 bundled shiki themes are supported. When omitted, the viewer uses your site's Tailwind theme colors.

Dracula

Dracula

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

Nord

Nord

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

Tokyo Night

Tokyo Night

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

Catppuccin Mocha

Catppuccin Mocha

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

One Dark Pro

One Dark Pro

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

GitHub Light

GitHub Light

8 keys
"response": {
"id": "usr_7k2m9p",
"email": "jamie@example.com",
"name": "Jamie Chen",
"role": "admin",
"verified": true,
"created_at": "2026-03-10T23:42:00Z",
"metadata": {
"login_count": 142,
"last_ip": "203.0.113.42",
"preferences": {3 items}
},
"teams": [
0: {3 items},
1: {3 items}
]
}

Features

  • Path copying. Hover any row and click the path icon to copy the JavaScript access path (e.g. response.teams[0].name). Handles bracket notation for non-identifier keys.
  • Search. Toggle the search bar to filter keys and values. Matching text is highlighted inline and non-matching branches are hidden.
  • Expand / collapse all. Toolbar buttons to expand or collapse the entire tree at once.
  • Copy JSON. One-click copy of the full JSON with pretty-print formatting.

API Reference

JsonViewer

PropType

Notes

  • Client component. Uses "use client" for expand/collapse state, search, and clipboard access.
  • No virtualization. Renders all nodes directly. Suitable for typical API payloads (up to a few hundred nodes). For very large datasets, consider truncating the data before passing it in.
  • Search behavior. When a search query is active, the tree auto-expands all nodes and hides branches with no matches. Clear the search to restore the previous collapse state.
  • Path format. Copied paths use JavaScript dot notation for valid identifiers and bracket notation for numeric indices or special characters (e.g. root["special-key"]).
  • No dependencies. Only requires React, Tailwind, lucide-react, and the cn utility.