Find your next tool

Browse tools or search by task

Explore JSONToonPro

JSON Tools

JSON to HTML Table Converter – Generate Table Code

Convert JSON arrays into clean HTML table markup online. Preview rows and columns, copy table code and keep source data in your browser.

Runs locally in your browser. Nothing you paste is uploaded.

JSON to HTML Table workspace
Class
3 rows × 5 cols
Input/ JSON
385 chars23 lines
Output/ HTML
585 chars34 lines

How to Convert JSON to an HTML Table

Paste an array of JSON records and preview the table. Copy the generated HTML when rows and headers match the data. This tool builds table markup, not a full web page or a data-grid application.

Mapping JSON Keys to Table Columns

Object keys become column headings and each record contributes a row. Missing values need a consistent empty-cell representation. Check header order if another system expects specific columns.

Nested JSON and Flattening Choices

A nested value is not a native table cell. Flatten beforehand when you need individual nested fields as columns, or keep serialized values for a compact overview. Review wide tables on small screens.

HTML Table Output and Styling

Use the generated markup as a starting point and apply your site’s table styles. Keep header cells associated with data cells. Treat untrusted source values as text rather than injecting them as executable HTML.

JSON to HTML Table Examples

The array [{"name":"Ada","score":9}] becomes a header row and one data row. Check special characters such as angle brackets and ampersands. Add a caption when the table needs context in a document.

More examples and technical details

Semantic Table Markup

A correct HTML table is more than rows of cells. The elements carry meaning that browsers, screen readers, and search engines all rely on, and using the right ones costs nothing extra.

  • table wraps the whole grid and declares that this is tabular data.
  • caption gives the table a title. It must be the first child of table, and it is announced before the content.
  • thead holds the header row. Browsers repeat it across pages when printing.
  • tbody holds the data rows. It is inserted automatically if you omit it, so writing it explicitly keeps your source matching the rendered DOM.
  • th marks a header cell, styled bold and centred by default and, more importantly, treated as a label for the cells it governs.
  • td marks a data cell.
  • tfoot holds totals and summary rows, and may appear before or after tbody in the source.

Side by Side Example

A pricing table generated from a JSON array.

JSON input

[
{ "plan": "Starter",
"seats": 3,
"monthly": "£9",
"note": "Fair use & basic support" },
{ "plan": "Team",
"seats": 25,
"monthly": "£39",
"note": "Priority support" },
{ "plan": "Scale",
"seats": 250,
"monthly": "£149",
"note": "SLA <4h response" }
]

HTML output

<table>
<caption>Pricing plans</caption>
<thead>
<tr>
<th scope="col">plan</th>
<th scope="col">seats</th>
<th scope="col">monthly</th>
<th scope="col">note</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Starter</th>
<td>3</td>
<td>&pound;9</td>
<td>Fair use &amp; basic support</td>
</tr>
<tr>
<th scope="row">Scale</th>
<td>250</td>
<td>&pound;149</td>
<td>SLA &lt;4h response</td>
</tr>
</tbody>
</table>

The ampersand and the less-than sign in the note column are escaped. Without that, the last row would swallow everything after &lt;4h as an unknown tag.

Accessibility Requirements

Screen readers navigate tables cell by cell and announce the relevant headers as they go. That only works if the markup says which headers apply.

RequirementHowWhy it matters
Header directionscope="col" or scope="row" on every thTells assistive tech which cells a header labels
Table titleA caption elementAnnounced first, so a user knows what they entered
Row headersFirst cell of each row as th, not tdGives every data cell a row label as well as a column one
Complex headersheaders and id attributesNeeded when a cell has more than one applicable header
No layout tablesUse CSS grid or flexbox for layoutA layout table is announced as data and is meaningless read aloud
role="presentation"Only on unavoidable legacy layout tablesStrips table semantics so it is not announced as a grid

Using a table for page layout was standard practice twenty years ago and is now simply wrong. A screen reader announces a five column table and starts reading coordinates, which is a genuinely disorienting experience. CSS handles layout, tables handle data.

Escaping Before Insertion

Any value that came from a user, an upload, or an external API is untrusted, and inserting it into HTML without escaping is a cross site scripting vulnerability.

The five characters and the safe pattern

& -> &amp; < -> &lt; > -> &gt;
" -> &quot; ' -> &#39;
 
// Unsafe: parses and executes the value as markup
cell.innerHTML = value;
 
// Safe: inserts the value as text, whatever it contains
cell.textContent = value;

Escape the ampersand first, otherwise you will double escape the entities you just produced. Framework templating in React, Vue, Angular, and most server side template engines escapes interpolated values by default, so the danger is concentrated in the escape hatches: dangerouslySetInnerHTML, v-html, and any raw string concatenation. Escape attribute values too, since a stray quote inside an attribute lets an attacker close it and add another one.

Responsive Strategies for Wide Tables

Tables do not reflow. A ten column table on a 375 pixel screen has to give somewhere, and there are two approaches that work.

Horizontal scroll on a wrapper

<div class="table-wrap" role="region"
aria-label="Pricing plans" tabindex="0">
<table> ... </table>
</div>
 
.table-wrap { overflow-x: auto; }
table { min-width: 640px; }

The wrapper, not the table, gets the overflow. The tabindex makes the scrollable region reachable by keyboard, which is a requirement rather than a nicety, and the label tells a screen reader what the region contains. This preserves the table semantics completely and is the right default.

The alternative is a card layout below a breakpoint, where each row becomes a stacked block and the column name is shown as a label using a data attribute and a CSS pseudo element. It reads better on a phone for tables of five or six columns, and it is worse for anything where comparing values across rows is the point, since the alignment that made comparison easy is gone.

Light Styling and Where the Output Goes

Zebra striping and a sticky header

table { border-collapse: collapse; width: 100%; }
th, td { padding: 8px 12px; text-align: left; }
tbody tr:nth-child(even) { background: #fafbfc; }
thead th { position: sticky; top: 0; background: #fff; }
td.num { text-align: right;
font-variant-numeric: tabular-nums; }

Right align numeric columns and use tabular figures so the digits line up in columns. It makes scanning for magnitude far easier and it is one line of CSS.

Generated tables end up in a few predictable places. HTML email is the most demanding, since many clients support only inline styles and a limited CSS subset, so keep the markup simple and put styles on the elements. Documentation sites, CMS pages, and static site builds are the common cases, and there a semantic table with a stylesheet is ideal. Internal reports and exported dashboards round out the list.

Tables travel between formats constantly. Check the full converter collection for JSON to Markdown when the destination is a README rather than a web page, JSON to CSV when someone wants it in a spreadsheet, and JSON to Excel for a formatted workbook.

Standards and references

Frequently asked questions

How do I turn JSON into an HTML table?

Paste a JSON record array, review the table preview and copy the HTML.

Can nested JSON be flattened into columns?

Flatten the input when nested properties need independent columns; review the resulting shape.

Does the tool include CSS styles?

The generated table can be styled with your own CSS; inspect the output before embedding it.

Can I copy only the HTML markup?

Yes. Copy the generated HTML output.

Is JSON uploaded?

No. Input is processed in this browser tab and is not uploaded by the tool. Copy and download are actions you control; ordinary page analytics do not receive tool input.