How to Convert JSON to an HTML Table

Every developer eventually stares at a raw JSON array and thinks: this needs to be a table.

Whether you’re displaying API response data in a dashboard or rendering database results on a page, knowing how to convert JSON to an HTML table is a practical skill that comes up constantly.

The process looks simple on the surface. It gets tricky once you hit nested objects, inconsistent keys, or a backend language you’re less comfortable with.

This guide covers every major method: vanilla JavaScript DOM manipulation, libraries like DataTables.js and Tabulator, server-side rendering with Python, PHP, and Node.js, plus quick online tools for non-code situations.

By the end, you’ll know exactly which approach fits your setup.

What Is JSON-to-HTML Table Conversion

JSON-to-HTML table conversion is the process of mapping JSON key-value pairs or array objects into structured <table> rows and columns that a browser can render.

It sounds straightforward. And for flat JSON it is. The moment you add nesting, things get tricky fast.

REST APIs power 83% of all web services (RapidAPI Developer Survey), and almost all of them return JSON. That makes the ability to display that data in a readable table one of the most common frontend tasks there is.

What JSON structure looks like before conversion

Flat JSON is the easiest case. Each object in the array becomes one row, and the keys become column headers.

[
{ "name": "Alice", "role": "Developer", "age": 30 },
{ "name": "Bob",   "role": "Designer",  "age": 27 }
]

Nested JSON is where most developers get stuck. A value that’s an object or array won’t render cleanly as a table cell without extra handling.

[
{ "name": "Alice", "address": { "city": "Berlin", "zip": "10115" } }
]

For nested structures, you have two options: flatten the object before rendering, or stringify the nested value as a fallback.

Common use cases

Most of the time you’re converting JSON to a table in one of these scenarios:

  • Displaying API responses in admin dashboards
  • Building data-heavy reporting tools
  • Rendering database query results on a frontend
  • Showing product or pricing data on a public page

The method you pick depends on the context. A quick internal dashboard has different needs than a customer-facing HTML table that needs sorting, filtering, and a clean visual design.

When conversion complexity increases

Key factor: JSON structure depth.

JSON type Conversion effort Best approach
wpDataTables Low Link JSON URL, select root, save
Flat array of objects Low Vanilla JavaScript loop
Array with some nested keys Medium Flatten before rendering
Deeply nested or recursive High Library or server-side render
Mixed types (arrays + objects) High Normalize schema first

Methods to Convert JSON to an HTML Table

There are four main ways to go about this. Each one has a different tradeoff between setup time, flexibility, and how much control you need over the output.

Method Best for Dependencies
wpDataTables WordPress Any JSON via URL, no coding needed wpDataTables plugin
Vanilla JavaScript Simple flat JSON, no extra libraries None
JS libraries (DataTables, Tabulator) Sorting, filtering, pagination built in Library required
Server-side (Python, PHP, Node.js) Data processed before reaching the browser Backend environment
Online converters One-off conversions, no coding needed None

For most developers working on real projects, vanilla JavaScript covers a surprising number of cases. Libraries become worth the extra weight when you need user interaction: sorting columns, filtering rows, or table pagination.

Server-side rendering makes sense when the dataset is large or when you need to avoid exposing your API response structure to the client.

Convert JSON to an HTML Table with wpDataTables

Prepare Your JSON Data

Before anything else, your JSON needs to meet a few requirements:

  • The dataset must not be empty (at least 1-2 rows)
  • It must be accessible via a public URL that wpDataTables can reach
  • Flat JSON must follow this structure: an array of same-structured objects, where each object becomes a row and each field becomes a column
  • Nested JSON must start with a root object (not an opening square bracket [), otherwise the plugin will return an error

Create a New Table

  1. Go to wpDataTables > Create a Table in your WordPress dashboard
  2. Select “Create a data table linked to an existing data source”
  3. Enter a name for the table in the wpDataTable name field (don’t skip this)

Set the Input Data Source

This is where the original steps get a bit muddled, so pay attention here.

For flat JSON:

  • Set the input data source type to JSON
  • Paste your JSON file URL into the Input JSON URL field

For nested JSON:

  • Set the input data source type to Nested JSON
  • Paste your JSON URL into the input field

If your JSON URL contains special characters, wpDataTables will sanitize them automatically.

Get JSON Roots (Nested JSON Only)

Click the “Get JSON roots” button. This reads your data structure and gives you a dropdown to choose which level to use for the table.

Select the appropriate level (for example, "results" or "films" depending on your data). You can only select one level.

Note: If the button gets stuck, hit Save Changes, reload the page, then try again.

Save the Table

Click Save Changes. wpDataTables will generate the table and produce a shortcode.

Add the Table to a Page

A few options here:

  • Classic editor: Click “Insert wpDataTable” in the editor toolbar, locate your table, and click OK
  • Gutenberg, Elementor, or WPBakery: Use the dedicated wpDataTables block or element
  • Any editor: Paste the shortcode directly into your page or post

Important Limitations to Know

Once the table is created, don’t change the structure of your JSON source file. Adding or removing columns will break the table and you’ll need to recreate it from scratch.

Also, these tables are non-server-side by default. All data is loaded to the front end and processed by JavaScript. If your JSON has more than 2,000-3,000 rows, turn on the Caching option to keep performance reasonable.

Convert JSON to an HTML Table with Vanilla JavaScript

This is the dependency-free approach. No libraries, no build tools. Just the DOM API and a loop.

JavaScript was the preferred language of 62.3% of developers in 2024 (Stack Overflow Developer Survey), and most of them already know enough DOM manipulation to build a dynamic table without reaching for a package.

The core logic

The pattern is always the same: parse the JSON, extract the keys for headers, loop through the array to create rows.

function jsonToTable(data) {
if (!data || !data.length) return;

const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');

// Build header row from first object's keys
const headers = Object.keys(data[0]);
const headerRow = document.createElement('tr');
headers.forEach(key => {
const th = document.createElement('th');
th.textContent = key;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);

// Build data rows
data.forEach(item => {
const tr = document.createElement('tr');
headers.forEach(key => {
const td = document.createElement('td');
td.textContent = item[key] ?? '';
tr.appendChild(td);
});
tbody.appendChild(tr);
});

table.appendChild(thead);
table.appendChild(tbody);
document.body.appendChild(table);
}

The ?? '' on the td value handles missing or null keys gracefully. Without it, you get “undefined” printed in cells. I’ve seen that bug in production more times than I’d like to admit.

Handle nested JSON in the table

Nested objects break the simple approach. item[key] returns [object Object] instead of something useful.

Option 1 – Flatten before rendering. Write a function that converts { address: { city: "Berlin" } } into { "address.city": "Berlin" }. Then run your normal loop.

function flattenObject(obj, prefix = '') {
return Object.keys(obj).reduce((acc, key) => {
const fullKey = prefix ? `${prefix}.${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
Object.assign(acc, flattenObject(obj[key], fullKey));
} else {
acc[fullKey] = obj[key];
}
return acc;
}, {});
}

Option 2 – Stringify as fallback. If you just need something readable and don’t care about column consistency, use JSON.stringify(item[key]) for any value that’s an object or array.

The flatten approach gives you proper column separation. The stringify approach is faster to write but messy for anything beyond one level deep.

Limitations to know

  • No built-in sorting or filtering
  • No pagination for large datasets
  • Inconsistent JSON keys across objects will create misaligned columns
  • No XSS protection unless you sanitize cell values

That last one matters. If your JSON comes from user input or an external API, use textContent (not innerHTML) when setting cell values. Using innerHTML with unsanitized data is a common source of cross-site scripting vulnerabilities.

Convert JSON to an HTML Table Using JavaScript Libraries

Libraries become worth it the moment your table needs user interaction. Sorting, filtering, search, and pagination are all non-trivial to build from scratch and very easy with the right tool.

According to npm trends, tabulator-tables pulls around 115,000 weekly downloads while the core datatables package sits at roughly 40,000. Both are actively maintained and well-documented.

DataTables.js

DataTables is probably the most widely known option. It wraps an existing HTML table or pulls data directly from a JSON source.

$(document).ready(function() {
$('#myTable').DataTable({
ajax: {
url: '/api/data',
dataSrc: ''  // if your JSON is a top-level array
},
columns: [
{ title: 'Name', data: 'name' },
{ title: 'Role', data: 'role' },
{ title: 'Age',  data: 'age'  }
]
});
});

The dataSrc property is where most people get stuck. If your API returns { "data": [...] }, use dataSrc: 'data'. If it returns a plain array, use dataSrc: ''.

Tabulator.js

Tabulator handles nested data better than DataTables and doesn’t require jQuery. It also has cleaner support for editable cells and row-level actions, which matters for admin tools.

const table = new Tabulator('#myTable', {
data: jsonData,
autoColumns: true,  // generates columns from JSON keys automatically
});

autoColumns: true is genuinely useful for prototyping. It reads the JSON keys and builds column definitions on the fly. You’d turn it off in production and define columns manually for better control.

AG Grid (Community Edition)

AG Grid is a step up in complexity but handles large datasets far better than either of the above. It supports virtual scrolling, which means it only renders the rows visible in the viewport. Useful for anything over a few thousand rows.

Worth considering if you’re building something closer to a spreadsheet than a simple data display. For most standard use cases, Tabulator or DataTables is plenty.

Quick comparison

Library jQuery Required Nested Data Best For
DataTables.js Yes Limited Standard tables with AJAX source
Tabulator.js No Good Modern apps, editable grids
AG Grid Community No Good Large datasets, enterprise-style UI

Convert JSON to an HTML Table in Python

Python is the go-to for server-side JSON-to-table conversion, mostly because pandas makes it almost trivially easy. Python has been growing steadily and sits at 51% usage among developers in 2024 (Stack Overflow Developer Survey), making it a very common backend choice alongside JavaScript.

Using pandas DataFrame.to_html()

This is the fastest path for anyone already working with data in pandas.

import pandas as pd
import json

with open('data.json') as f:
data = json.load(f)

df = pd.DataFrame(data)
html_table = df.to_html(index=False, classes='data-table', border=0)

with open('output.html', 'w') as f:
f.write(html_table)

index=False removes the row numbers from the output. You almost always want this. The classes parameter lets you attach CSS class names for styling without touching the HTML manually.

Other useful parameters:

  • na_rep='N/A' – replaces NaN values with readable text
  • float_format='%.2f' – formats floats to 2 decimal places
  • escape=True – escapes HTML special characters (leave this on for security)
  • table_id='myTable' – adds an id attribute to the table element

Using Flask or Django for web rendering

If you’re serving this table through a web framework, the pattern shifts slightly. In Flask, you convert the DataFrame to HTML and pass that string to your template.

from flask import Flask, render_template_string
import pandas as pd

app = Flask(__name__)

@app.route('/table')
def show_table():
df = pd.read_json('data.json')
table_html = df.to_html(index=False, classes='table')
return render_template_string('<html><body>{{ table|safe }}</body></html>',
table=table_html)

The |safe filter in Jinja2 tells the template engine not to escape the HTML string. Without it, your table renders as raw text. Just make sure the data feeding the table is sanitized before you get to this step.

Manual approach without pandas

If pandas isn’t available or the overhead isn’t worth it for a simple task:

import json

with open('data.json') as f:
data = json.load(f)

headers = data[0].keys()
rows = [list(item.values()) for item in data]

html = '<table><thead><tr>'
html += ''.join(f'<th>{h}</th>' for h in headers)
html += '</tr></thead><tbody>'
for row in rows:
html += '<tr>' + ''.join(f'<td>{cell}</td>' for cell in row) + '</tr>'
html += '</tbody></table>'

Clean and dependency-free. Works fine for small datasets. For anything over a few hundred rows, you’ll want pandas or a proper template engine doing the heavy lifting.

Convert JSON to an HTML Table in PHP

PHP is still running a massive share of the web. WordPress alone powers over 43% of all websites (W3Techs, 2024), and most WordPress-adjacent backends end up needing to render JSON data as tables at some point.

Basic approach with json_decode()

PHP’s built-in json_decode() handles the JSON parsing. Set the second argument to true to get an associative array instead of an object, which is easier to loop through.

<?php
$jsonData = file_get_contents('data.json');
$data = json_decode($jsonData, true);

if (!empty($data)) {
$headers = array_keys($data[0]);

echo '<table><thead><tr>';
foreach ($headers as $header) {
echo '<th>' . htmlspecialchars($header) . '</th>';
}
echo '</tr></thead><tbody>';

foreach ($data as $row) {
echo '<tr>';
foreach ($headers as $key) {
$value = isset($row[$key]) ? $row[$key] : '';
echo '<td>' . htmlspecialchars($value) . '</td>';
}
echo '</tr>';
}

echo '</tbody></table>';
}
?>

htmlspecialchars() is doing the security work here. It converts characters like < and > into their HTML entities, which blocks XSS injection through table cell values. Skipping this is one of the most common PHP security mistakes.

Handling associative vs. indexed arrays

Not all JSON is an array of objects. Sometimes you get an indexed array or a mixed structure. A quick check before rendering saves debugging time later.

<?php
// Check if it's an array of objects (associative arrays in PHP)
if (isset($data[0]) && is_array($data[0])) {
// Proceed with header extraction from first element
$headers = array_keys($data[0]);
} else {
// Handle single object or unexpected structure
$data = [$data];
$headers = array_keys($data[0]);
}
?>

I’ve seen developers skip this check and then spend 30 minutes wondering why their table only shows one column. The JSON shape coming from a third-party API isn’t always what you expect.

Fetching JSON from an external API

If the JSON is coming from an external source rather than a local file, use file_get_contents() with a URL or, better, use cURL for more control over headers and timeouts.

<?php
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
?>

cURL gives you timeout control, which matters. A hanging file_get_contents() call to a slow external API can lock up an entire PHP process.

Convert JSON to an HTML Table in Node.js

Node.js is used by 40.8% of developers as their preferred runtime environment, according to the 2024 State of JavaScript survey. When your JSON-to-table conversion needs to happen server-side in a JavaScript environment, Node.js with Express is the most common path.

The main reason to render server-side with Node rather than in the browser: you avoid exposing your API structure, and you can cache the rendered HTML output.

Manual approach with template literals

No npm package needed. Template literals make building HTML strings clean and readable in Node.js.

function buildTable(data) {
if (!data || !data.length) return '<p>No data</p>';

const headers = Object.keys(data[0]);
const ths = headers.map(h => `<th>${h}</th>`).join('');
const rows = data.map(row =>
`<tr>${headers.map(h => `<td>${row[h] ?? ''}</td>`).join('')}</tr>`
).join('');

return `<table><thead><tr>${ths}</tr></thead><tbody>${rows}</tbody></table>`;
}

Call this inside an Express route and send the result as an HTML response or pass it to a template engine like EJS or Handlebars.

Using npm packages for table generation

The npm registry has over 1.3 million packages available (GeeksforGeeks, 2024). A few are worth knowing for JSON table work specifically.

  • json2html: converts JSON to HTML strings using template mappings
  • table: renders JSON data as a formatted string table (better for CLI output than browser HTML)
  • consolidate.js: pairs well with template engines for structured HTML rendering

Honestly, for most Express apps, a simple template literal function or an EJS partial is cleaner than pulling in a package for this.

Serving the table via Express

Full Express example:

const express = require('express');
const app = express();

app.get('/table', async (req, res) => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
const tableHtml = buildTable(data);
res.send(`<html><body>${tableHtml}</body></html>`);
});

app.listen(3000);

If the JSON comes from an external REST API, the fetch call handles the JSON parsing. Pass the resulting array directly into your table builder.

One thing worth knowing: Node.js has no built-in fetch before version 18. If you’re on an older version, use the node-fetch package or the built-in https module instead.

Online Tools to Convert JSON to an HTML Table

Not every JSON-to-table task needs code. For one-off jobs, quick reports, or prototyping a layout before you build anything, online converters do the job in seconds.

Tools worth knowing

Tool Best For Limitation
TableConvert.com Flat JSON, multi-format export No dynamic data support
ConvertJSON.com Quick paste-and-convert Basic styling only
JSON to HTML Table (various) Simple one-level JSON arrays Nested objects break output

All of these tools work the same way. Paste your JSON, click convert, copy the HTML output. Done.

When online tools make sense

Good for:

  • Internal reports where styling doesn’t matter much
  • Prototyping a table structure before writing any code
  • Non-developers who need to share tabular data quickly

Not suitable for: live data, any JSON with nesting deeper than one level, or situations where you need sorting, filtering, or custom column logic. They also give you zero control over CSS classes or attribute output.

Privacy consideration

Pasting JSON into a third-party online tool means that data leaves your environment. If your JSON contains user data, API keys, or anything sensitive, use a local conversion method instead. Most of these tools don’t advertise data retention policies clearly.

Style the HTML Table After Conversion

A raw, unstyled HTML table works. But nobody wants to look at one. The State of HTML 2024 survey (web.dev) found that 51% of developers asked for better data table support, which suggests table rendering and presentation are still a real friction point in frontend work.

Good news: most of the styling work is straightforward once you know where to hook in.

Add CSS classes during generation

The right time to add classes is when you build the table, not after. Retrofitting classes onto a rendered table with JavaScript is fragile.

In JavaScript: pass a class name into your table creation function.

const table = document.createElement('table');
table.className = 'data-table';  // add at creation time

In Python pandas: use the classes parameter directly.

df.to_html(classes='data-table striped', index=False)

Then target .data-table in your CSS for all visual styling. Clean separation.

Bootstrap table classes

Bootstrap is used by 77.5% of websites using a known CSS framework (Quora, June 2024). If Bootstrap is already in your project, you get a lot of table styling for free.

  • table – base styles, full-width, padded cells
  • table-striped – alternating row colors
  • table-hover – row highlight on hover
  • table-bordered – visible table border on all cells
  • table-sm – reduced cell padding for dense data

Wrap the table in a div with class table-responsive to get horizontal scrolling on small screens without extra CSS.

Responsive table without a framework

If you’re not using Bootstrap, a responsive table wrapper is two lines of CSS.

.table-wrapper {
overflow-x: auto;
width: 100%;
}

table {
min-width: 600px;
border-collapse: collapse;
}

Set min-width to roughly the width the table needs to display all columns legibly. The wrapper handles scrolling on narrower viewports.

Sticky headers and alternating rows

Sticky header: keeps column labels visible as users scroll through long data sets.

thead th {
position: sticky;
top: 0;
background: #fff;
z-index: 1;
}

Alternating rows (zebra striping) improve readability on dense tables. No JavaScript needed.

tbody tr:nth-child(even) {
background-color: #f5f5f5;
}

For more complete control over HTML table design including color, typography, and layout patterns, it’s worth looking at what a purpose-built table solution handles for you versus writing everything from scratch.

Common Errors When Converting JSON to an HTML Table

Most JSON-to-table bugs come from the same small set of problems. Knowing them upfront saves a lot of time.

[object Object] in table cells

This one shows up constantly. It happens when a cell value is a nested object or array and you’re setting it with textContent or string concatenation.

The fix: check the value type before rendering.

const value = typeof item[key] === 'object' && item[key] !== null
? JSON.stringify(item[key])
: item[key] ?? '';

Not pretty in the table, but at least it shows something useful instead of [object Object].

Empty table from wrong array path

Your API returns { "results": [...] } but your code tries to loop over the whole response object.

// Wrong
const data = await response.json();
buildTable(data);  // data is an object, not an array

// Right
const json = await response.json();
buildTable(json.results);  // access the actual array

Always log the raw response before you try to render it. One console.log(data) saves 20 minutes of debugging.

CORS errors when fetching external JSON

If your JSON comes from a different domain and you’re fetching it client-side, you’ll likely hit a CORS block. The browser enforces this, not your code.

  • Use a server-side fetch (Node.js, PHP, Python) to proxy the request
  • Check if the API offers a CORS-friendly endpoint
  • Add the appropriate Access-Control-Allow-Origin header if you control the API

There’s no client-side workaround for CORS. If the API doesn’t allow cross-origin requests, the request has to go through your backend.

Inconsistent JSON keys breaking column alignment

Some APIs return objects where not every item has the same keys. Row 1 has { name, role, age }. Row 5 has { name, role }. The table renders with a missing cell.

// Use the full key set from all objects, not just the first
const headers = [...new Set(data.flatMap(item => Object.keys(item)))];

This collects every key that appears across all objects. Then when you render a row, use item[key] ?? '' so missing keys just produce empty cells instead of errors.

Unescaped HTML characters causing broken output

If a JSON value contains <, >, or &, rendering it with innerHTML will either break your table structure or introduce a JavaScript data table security risk.

Use textContent instead of innerHTML when inserting cell values in vanilla JavaScript. That’s the simplest, most reliable fix.

In PHP, always wrap output in htmlspecialchars(). XSS through JSON-rendered tables is a real attack vector, and it’s entirely preventable with one function call.

FAQ on How To Convert JSON To An HTML Table

Can I convert JSON to an HTML table without a library?

Yes. Vanilla JavaScript handles it cleanly. Use Object.keys() to extract headers from the first object, then loop through the array with forEach to build <tr> and <td> elements dynamically. No dependencies needed.

What is the fastest way to render JSON as a table in JavaScript?

Build the table string with innerHTML in one pass rather than appending individual DOM nodes. For large datasets, this is noticeably faster. Use template literals to keep the code readable while batching all row generation into a single DOM write.

How do I handle nested JSON objects in a table?

Flatten nested objects before rendering. A recursive flatten function converts { address: { city: "Berlin" } } into { "address.city": "Berlin" }. As a fallback, use JSON.stringify() on any value that’s still an object after flattening.

How do I convert JSON to an HTML table in Python?

Use pandas. Load your JSON into a DataFrame, then call df.to_html(index=False). Pass the classes parameter to attach CSS class names. Works directly in Flask and Django templates with minimal extra code.

How do I dynamically create a table from a JSON API response?

Fetch the endpoint with the Fetch API, parse the response with .json(), then pass the resulting array into your table-building function. Handle the dataSrc path carefully if the array is nested inside a wrapper object.

Why does my table show [object Object] in some cells?

A cell value is a nested object or array. JavaScript coerces it to the string [object Object] automatically. Check the value type before rendering and use JSON.stringify() for any value that isn’t a primitive string, number, or boolean.

How do I make the generated HTML table responsive?

Wrap the table in a div with overflow-x: auto. Set a min-width on the table itself. If Bootstrap is available, the table-responsive wrapper class handles this. Check out mobile-friendly tables for additional techniques.

Can I add sorting and filtering to a JSON-generated table?

Not with plain HTML alone. Use DataTables.js or Tabulator.js, both of which accept a JSON data source directly and add sorting, filtering, and pagination out of the box. AG Grid handles larger datasets better.

How do I convert JSON to an HTML table in PHP?

Use json_decode($json, true) to parse the JSON into an associative array, then loop with foreach. Always wrap output in htmlspecialchars() to block XSS. Extract headers from array_keys() on the first row.

Are there online tools to convert JSON to an HTML table without coding?

Yes. TableConvert.com and ConvertJSON.com both handle flat JSON arrays well. Paste your JSON, copy the HTML output. These tools work for quick one-off conversions but don’t support nested objects, dynamic data, or custom HTML table headers.

Conclusion

This conclusion is for an article presenting the full range of ways to build an HTML table from JSON data, from a bare JavaScript loop to pandas DataFrames and PHP arrays.

The right method depends on your stack. Vanilla JavaScript works for flat, client-side rendering. Libraries like DataTables.js and Tabulator add sorting and pagination when you need them. Python, PHP, and Node.js each handle server-side rendering cleanly.

Nested JSON, inconsistent keys, and unescaped output cause most of the real problems. Handle those early.

Whatever approach you pick, apply CSS classes at generation time, keep XSS protection in mind, and test with messy real-world JSON before shipping.


Milan Jovanovic
Milan Jovanovic

Product Lead

Articles: 281