JSON

HTML table

Your table markup appears here

Paste a JSON array on the left. The HTML is built as you type.

When you need the markup, not a preview

Plenty of tools will show you JSON as a table on screen. This one gives you the <table> element itself — the markup you paste into a page, a template, a CMS block or an email. Paste an array on the left, take the HTML from the right.

The part that takes ten minutes to get right by hand, and that a naive script gets wrong, is escaping. A value holding Tom & Jerry has to become Tom &amp; Jerry, and the ampersand must be escaped before the angle brackets — do it the other way round and the &lt; you just wrote gets its own ampersand escaped, so < renders on the page as the literal text &lt;. It is a one-line ordering mistake with a very confusing symptom.

Escaping is also a safety question, not just a rendering one. If a value in your data contains <img src=x onerror=…> and you paste it unescaped into a page, that becomes a live element — and you pasted it yourself, believing it was data. The OWASP cross-site scripting prevention cheat sheet is the short version of why this matters even for data you think you control.

Header cells come out as <th scope="col"> rather than bare <td>. That attribute is what tells a screen reader which header a given cell belongs to, and the W3C's tables tutorial asks for it on any table with a header row. Generated tables are exactly where it gets left out — nobody hand-writes the headers, so nobody remembers.

How to use it

  1. Paste your JSON – An array of objects. A lone object becomes a single row, and a {"data": [...]} wrapper is read through to the array inside.
  2. Choose the styling – Plain gives you bare semantic markup to style with your own CSS. Bootstrap adds the classes this site itself uses. Inline CSS puts the borders and padding in style attributes.
  3. Decide on thead and tbody – Leave it on for a standalone table. Turn it off when you are pasting rows into a table that already exists and already has a header.
  4. Copy the markup, or download an .html file – Downloading gives you a fragment, not a whole document — it is meant to go inside a page you already have.

Pro tip: pick Inline CSS when the destination strips stylesheets. Email clients are the obvious case — most of them drop a <style> block entirely — but so do a lot of CMS rich-text fields and internal wiki editors. Inline styles survive all of them.

A worked example

Two network KPI readings. Watch the cell IDs: they are 19 digits, and each one carries an extra style attribute in the output. That is a Microsoft Office instruction — it tells Excel to treat the cell as text if you paste this table into a spreadsheet, because Excel otherwise rounds anything past about 15 digits and the last four would silently change.

JSON array → HTML tableConvert
kpi.jsonJSON · 2 records
[
  {
    "cellId": 2145829461037584512,
    "site": "Bristol-Central-3",
    "rsrp": -97
  },
  {
    "cellId": 2145829461037591866,
    "site": "Bristol-Harbourside-1",
    "rsrp": -103
  }
]
kpi.htmlHTML · plain styling
<table>
  <thead>
    <tr>
      <th scope="col">cellId</th>
      <th scope="col">site</th>
      <th scope="col">rsrp</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="mso-number-format:'\@'">2145829461037584512</td>
      <td>Bristol-Central-3</td>
      <td>-97</td>
    </tr>
  </tbody>
</table>

Where this actually gets used

Dropping a data table into a static page

You have a page with no build step and no framework — a landing page, a docs page, an internal dashboard someone maintains by hand. The data lives in JSON somewhere. Convert it, paste the markup, style it with the CSS the page already has. The semantics are correct out of the box, which matters if the page is ever audited.

Sending a report by email

Email clients are hostile to CSS. A stylesheet block is stripped by most of them and external CSS never loads at all, so the only styling that reliably survives is on the element. Choosing inline CSS here produces a table that looks the same in a webmail client as it does in a desktop one, without you writing the same four declarations onto forty cells.

Pasting a table into a spreadsheet

Copying an HTML table into Excel or Google Sheets works surprisingly well — the cell boundaries come across intact. The trap is long numbers. An account number or a device identifier past fifteen digits gets rounded on paste, and the file looks completely normal afterwards. The cells that need it carry an Office-specific hint that forces them to text, so the digits arrive as they left. If you would rather have the file directly, JSON to Excel writes a real .xlsx.

What it handles

  • Escaped properly, in the right order& first, so nothing is double-escaped
  • Markup in your data stays data – a value containing a tag renders as text, not as an element
  • Scoped header cells<th scope="col">, so screen readers can associate cells with headers
  • Columns from every record – a field that appears only in later records still gets a column
  • Nested objects flatteneddevice.model as its own column
  • Long integers protected on paste – cells past 15 digits are pinned to text for Excel
  • Nothing leaves the browser – the conversion runs on your machine, with no upload

Questions people actually ask

Do I get a whole HTML document or just the table?

Just the <table> element. It is meant to go inside a page you already have, so wrapping it in <html> and <head> would give you something to delete every time. If you need a standalone file, paste the table into a minimal document yourself.

What is the odd style attribute on some cells?

mso-number-format is a Microsoft Office extension that forces a cell to be treated as text. It is added only to cells holding an integer long enough that Excel would round it — browsers ignore it completely, so it changes nothing about how the table renders on a web page.

Why turn off thead and tbody?

Because sometimes you are not making a whole table. If you are appending rows to a table that already exists in a page, you want <tr> elements and nothing else — the wrappers would produce a second header in the middle of someone else's table. That is the only reason to turn it off; for a standalone table, keep it.

Can I use my own CSS classes?

The Bootstrap option applies table table-bordered table-striped, which is what this site's own tables use. For anything else, take the plain output and add your classes — a find-and-replace on <table> is one edit, and it beats a text box that has to guess where you want the class to land.

How are nested arrays handled?

They stay in one cell as compact JSON. Spreading them into indexed columns would make the column count depend on whichever record was longest, and the header row would stop being readable. The MDN reference for the table element is worth a look if you want a genuinely nested layout — but that is a different structure from a flat grid of records.

Related tools

Worth reading