JSON Table

A shadcn/ui-compatible component that renders arbitrary JSON as a nested table.

Renders arbitrary JSON as a nested, recursive HTML table.

Open in
idnameemailactive
1
"Ada Lovelace"
"ada@example.com"
true
2
"Grace Hopper"
"grace@example.com"
true
3
"Alan Turing"
"alan@example.com"
false
npx shadcn@latest add https://json-table.kaylee.jp/r/json-table.json

Usage

Basic usage

Import from where the CLI installed it and pass your data.

import { JsonTable } from "@/components/ui/json-table"

const data = {
  id: 1,
  name: "Ada Lovelace",
  active: true,
}

export function Example() {
  return <JsonTable data={data} />
}

Styling and depth limit

className passes through; maxDepth guards against pathologically deep data.

import { JsonTable } from "@/components/ui/json-table"

export function Example({ data }: { data: unknown }) {
  return <JsonTable data={data} className="max-w-2xl" maxDepth={5} />
}

Localizing keys

keyTranslations maps a key name to a label. Values are never translated.

import { JsonTable } from "@/components/ui/json-table"

const keyTranslations = {
  name: "名前",
  email: "メール",
}

export function Example({ data }: { data: unknown }) {
  return <JsonTable data={data} keyTranslations={keyTranslations} />
}

Custom type colors

primitiveClassNames overrides the per-type value styling — pass your own classes, including theme tokens if your base color has distinguishable hues.

import { JsonTable } from "@/components/ui/json-table"

const primitiveClassNames = {
  string: "text-chart-1",
  number: "text-chart-2",
  boolean: "text-chart-4",
}

export function Example({ data }: { data: unknown }) {
  return <JsonTable data={data} primitiveClassNames={primitiveClassNames} />
}

Examples

Flat object

Primitives, null, and undefined are each styled distinctly.

id
42
name
"Ada Lovelace"
active
true
nickname
null
title
undefined
Raw JSON
{
  "id": 42,
  "name": "Ada Lovelace",
  "active": true,
  "nickname": null
}

Localized keys

keyTranslations maps a key to a label. Values are never translated.

ID名前メール有効
1
"Ada Lovelace"
"ada@example.com"
true
2
"Grace Hopper"
"grace@example.com"
true
3
"Alan Turing"
"alan@example.com"
false
Raw JSON
[
  {
    "id": 1,
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "active": true
  },
  {
    "id": 2,
    "name": "Grace Hopper",
    "email": "grace@example.com",
    "active": true
  },
  {
    "id": 3,
    "name": "Alan Turing",
    "email": "alan@example.com",
    "active": false
  }
]

Custom type colors

primitiveClassNames overridden here with this site's own chart tokens. Whether tokens stay colorful depends on the consumer's base color — plain Tailwind colors (the default) always are.

id
42
name
"Ada Lovelace"
active
true
nickname
null
title
undefined
Raw JSON
{
  "id": 42,
  "name": "Ada Lovelace",
  "active": true,
  "nickname": null
}

Array of objects with missing keys

Columns are the union of every item's keys.

idnameroleteam
1
"Ada Lovelace"
"Engineer"
2
"Grace Hopper"
3
"Alan Turing"
"Researcher"
"Cryptography"
Raw JSON
[
  {
    "id": 1,
    "name": "Ada Lovelace",
    "role": "Engineer"
  },
  {
    "id": 2,
    "name": "Grace Hopper"
  },
  {
    "id": 3,
    "name": "Alan Turing",
    "role": "Researcher",
    "team": "Cryptography"
  }
]

Arrays of primitives

Rendered inline rather than as a sub-table.

tags
"math", "computing", "history"
scores
98, 87, 91, 76
Raw JSON
{
  "tags": [
    "math",
    "computing",
    "history"
  ],
  "scores": [
    98,
    87,
    91,
    76
  ]
}

Deep nesting

Objects, arrays, and objects again, several levels deep.

organization
"Analytical Engines Inc."
departments
nameheadcountleadtags
"Engineering"
12
name
"Ada Lovelace"
email
"ada@example.com"
"core", "infra"
"Research"
4
name
"Alan Turing"
email
"alan@example.com"
"theory"
Raw JSON
{
  "organization": "Analytical Engines Inc.",
  "departments": [
    {
      "name": "Engineering",
      "headcount": 12,
      "lead": {
        "name": "Ada Lovelace",
        "email": "ada@example.com"
      },
      "tags": [
        "core",
        "infra"
      ]
    },
    {
      "name": "Research",
      "headcount": 4,
      "lead": {
        "name": "Alan Turing",
        "email": "alan@example.com"
      },
      "tags": [
        "theory"
      ]
    }
  ]
}

Edge cases

Empty object/array, a mixed-type array, and a wide table.

emptyObject
{}
emptyArray
[]
nullValue
null
mixedArray
  • 1
  • "two"
  • three
    3
  • 4, 5
wideTable
field_1field_2field_3field_4field_5field_6field_7field_8field_9field_10field_11field_12field_13field_14field_15field_16field_17field_18field_19field_20
0
7
14
21
28
35
42
49
56
63
70
77
84
91
98
105
112
119
126
133
0
7
14
21
28
35
42
49
56
63
70
77
84
91
98
105
112
119
126
133
Raw JSON
{
  "emptyObject": {},
  "emptyArray": [],
  "nullValue": null,
  "mixedArray": [
    1,
    "two",
    {
      "three": 3
    },
    [
      4,
      5
    ]
  ],
  "wideTable": [
    {
      "field_1": 0,
      "field_2": 7,
      "field_3": 14,
      "field_4": 21,
      "field_5": 28,
      "field_6": 35,
      "field_7": 42,
      "field_8": 49,
      "field_9": 56,
      "field_10": 63,
      "field_11": 70,
      "field_12": 77,
      "field_13": 84,
      "field_14": 91,
      "field_15": 98,
      "field_16": 105,
      "field_17": 112,
      "field_18": 119,
      "field_19": 126,
      "field_20": 133
    },
    "[Circular]"
  ]
}

Circular reference

A JS object graph pointing back at itself renders [Circular] instead of hanging.

name
"self-referencing"
self
[Circular]
Raw JSON
{
  "name": "self-referencing",
  "self": "[Circular]"
}