JSON to Table Converter

Paste a JSON array and read it as a table instead of scrolling through braces. Each object becomes a row and each top-level key a column. A record missing a field shows up as an empty cell. Nested objects are flattened into dotted columns such as user.name, and arrays appear as JSON text inside their cell. When the table looks right, take it with you: Copy for Email puts a bordered table on the clipboard that pastes into Gmail, Outlook, Google Docs, Word or Notion as a real table, Copy HTML gives clean <table> markup for a web page, and Copy Markdown gives a pipe table for a README, a GitHub issue or a Slack message.

JSON Input
Table Preview
Table will appear here...

1 JSON to Table example

Input JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
    {
        "id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "role": "Admin"
    },
    {
        "id": 2,
        "name": "Jane Smith",
        "email": "jane@example.com",
        "role": "User"
    }
]

Visual Table Output

Data rendered as responsive HTML table

id name role
1 John Admin
2 Jane User

2 What it makes visible

Missing fields

Records that lack a key show an empty cell. A gap in a column is easier to see than a missing line in a nested object.

Wrong types

Scan each column for the odd type out. A column of numbers with three quoted strings in it is a common reason a downstream parser or chart breaks.

Shape of a response

The column headers list every field in the response, so you see its shape without reading the API docs.

How to use the JSON to Table tool

  1. Paste a JSON array of objects into the left editor, or use Upload JSON, Load URL or Dummy Data. A sample table is shown when the page opens.
  2. The table redraws as you type. Click View Table to force a redraw after a large paste.
  3. Columns are the union of every key in every object, in the order they are first seen. A missing key produces an empty cell. A nested object is flattened into dotted columns such as address.city, and an array is shown as JSON text.
  4. If the input is invalid, the message above the editor reports the line number of the problem.
  5. Click Copy for Email to paste the table into Gmail, Outlook, Google Docs or Word, Copy HTML for clean <table> markup, or Copy Markdown for a GitHub pipe table. Each button reads the table currently shown, so sort or fix the data first.
  6. The record count sits in the footer. Clear empties the editor.

Rendering a JSON array as an HTML table in JavaScript, PHP and Python

JavaScript / Node.js

const data = [
  { id: 1, name: "John", role: "admin", tags: ["a", "b"] },
  { id: 2, name: "Jane", email: "jane@example.com" },
];

// Union of keys, in first-seen order, so ragged objects still line up
const columns = [...new Set(data.flatMap((row) => Object.keys(row)))];

const esc = (v) => String(v).replace(/&/g, "&amp;").replace(/</g, "&lt;");
const cell = (v) =>
  v === undefined || v === null ? "" : typeof v === "object" ? JSON.stringify(v) : v;

const html =
  `<table><thead><tr>${columns.map((c) => `<th>${esc(c)}</th>`).join("")}</tr></thead><tbody>` +
  data.map((row) => `<tr>${columns.map((c) => `<td>${esc(cell(row[c]))}</td>`).join("")}</tr>`).join("") +
  `</tbody></table>`;

console.log(html);
// In the browser: document.getElementById("out").innerHTML = html;

Escape every value before putting it in innerHTML; untrusted JSON can contain HTML.

PHP

<?php
$json = '[{"id":1,"name":"John","role":"admin","tags":["a","b"]},{"id":2,"name":"Jane","email":"jane@example.com"}]';
$rows = json_decode($json, true, 512, JSON_THROW_ON_ERROR);

// Collect every key that appears in any row
$columns = [];
foreach ($rows as $row) {
    $columns = array_unique(array_merge($columns, array_keys($row)));
}

echo "<table><thead><tr>";
foreach ($columns as $c) echo "<th>" . htmlspecialchars($c) . "</th>";
echo "</tr></thead><tbody>\n";
foreach ($rows as $row) {
    echo "<tr>";
    foreach ($columns as $c) {
        $v = $row[$c] ?? "";
        if (is_array($v)) $v = json_encode($v);
        echo "<td>" . htmlspecialchars((string) $v) . "</td>";
    }
    echo "</tr>\n";
}
echo "</tbody></table>\n";

Pass true as the second argument to json_decode() so objects become associative arrays.

Python

import json
from html import escape

raw = '[{"id":1,"name":"John","role":"admin","tags":["a","b"]},{"id":2,"name":"Jane","email":"jane@example.com"}]'
rows = json.loads(raw)
if isinstance(rows, dict):
    rows = [rows]

columns = list(dict.fromkeys(k for row in rows for k in row))

def cell(v):
    if v is None:
        return ""
    return json.dumps(v) if isinstance(v, (dict, list)) else str(v)

html = ["<table><thead><tr>" + "".join(f"<th>{escape(c)}</th>" for c in columns) + "</tr></thead><tbody>"]
for row in rows:
    html.append("<tr>" + "".join(f"<td>{escape(cell(row.get(c)))}</td>" for c in columns) + "</tr>")
html.append("</tbody></table>")
print("\n".join(html))

# With pandas: pandas.json_normalize(rows).to_html(index=False)

pandas.json_normalize() also flattens nested objects into dotted columns such as address.city.

Common errors and how to fix them

Error: Input must be a JSON array or object
The JSON is a bare string, number or null, which has no rows. Wrap the data in an array of objects, or paste the object that contains the list.
The table has a single column named Value
The array contains primitives such as [1, 2, 3] instead of objects. Each row needs an object with named keys to produce named columns.
Only one row appears but the API returned many records
The response wraps the list, for example {"data": [...]} or {"items": [...]}. Paste just the inner array so each element becomes a row.
A column is full of text like [{"city":"Oslo"}]
Those values are arrays. The viewer flattens nested objects into dotted columns such as address.city, but an array has no fixed set of columns, so it stays JSON text in one cell. Paste the inner array on its own to see each element as a row.
Error on line N after pasting from a log or a chat
Smart quotes, trailing commas or a truncated response make the JSON invalid. Run it through the JSON Formatter to find the exact token.

Good to know

A table is a rectangle and JSON is a tree. The viewer maps one onto the other by taking one array element per row and one column per key. Nested objects become dotted columns such as user.name, while arrays are shown as JSON text in the cell. Many data tools make the same choice, so if an API is meant for tabular use, return arrays of flat objects rather than nested documents.

Columns appear in the order their keys are first seen, so the first object usually sets the leading columns. If that first record is missing a field, the column shows up further right, after whichever record introduces it. Normalize the objects before pasting if the order matters for a screenshot or a report.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

What JSON structure does the viewer expect?

An array of objects. Each object becomes a row and the union of all keys becomes the columns. A single object is shown as a one-row table.

Can I sort the table?

No, the view is static. To sort or filter, convert the JSON to CSV or XLSX and open the result in a spreadsheet.

How are nested objects displayed?

Nested objects are flattened into dotted columns, so {"user": {"name": "Ada"}} gets a user.name column. Arrays are not flattened and show as JSON text inside their cell.

Can I load JSON from an API URL?

Yes, if the API allows cross-origin requests. Otherwise copy the response and paste it.

How do I paste a JSON array as a table into Gmail or Outlook?

Click Copy for Email and paste into the message body. The table goes onto the clipboard as rich text with inline borders and a shaded header row, which is the only kind of styling email clients keep. The same copy pastes as a native table into Google Docs, Word, Notion and Slack, so you can send an API response to a client without opening a spreadsheet.

What is the difference between Copy HTML and Copy for Email?

Copy HTML gives you code: indented <table>, <thead> and <tbody> tags with no classes or inline styles, for pasting into a page template, a CMS code editor or an HTML email template where your own CSS applies. Copy for Email gives you a rendered table with the styling baked in, for pasting into a visual editor. Use HTML when you will edit the markup, Email when you just want it to look right.

Can I convert JSON to a Markdown table?

Yes. Copy Markdown produces a GitHub-flavored pipe table with a header row and a --- separator line. Pipes inside a value are escaped and line breaks become <br>, so every record stays on one row. Paste it into a README, a GitHub or GitLab issue, Notion, Obsidian or a Discord message. If you need column alignment, use the JSON to Markdown tool instead.

What if my JSON is invalid?

The tool reports the parse error with its position. For more detail, paste it into the JSON Formatter, which highlights the exact problem.

Related

CSV to Table and PHP array to Table do the same for other sources. To export what you are looking at, use JSON to CSV or JSON to Excel.

More Data Viewers

Browse all data viewers

Copied to clipboard!