← Back to JavaScript Course | Chapter 9: Async & Web APIs | Lesson 25 of 26

JS JSON HTML

Once JSON data has been fetched and parsed, it usually needs to be turned into visible HTML on the page -- looping over an array of objects, building DOM elements or HTML strings for each one, and inserting the result into the page, being careful to escape any content that could otherwise be misinterpreted as HTML.

Building Elements from JSON with the DOM API

Looping over a parsed JSON array and, for each item, calling document.createElement() and setting properties (like textContent) builds real DOM elements safely -- textContent in particular ensures any text is treated as plain text, never interpreted as HTML.

Note: Use createElement() and textContent as the safest default approach for rendering JSON-derived content, especially when any of that content might originate from user input.

Warning: Building many elements this way, one .createElement() and several property assignments per item, is more verbose than building an HTML string, though noticeably safer by default.

Example: Building Elements from JSON with the DOM API

javascript
const items = [{ name: "Sam" }, { name: "Amit" }];
const list = document.createElement("ul");
items.forEach(item => {
  const li = document.createElement("li");
  li.textContent = item.name; // treated as plain text, never HTML
  list.appendChild(li);
});
document.body.appendChild(list);

Building an HTML String with Template Literals

Combining .map() with a template literal produces an HTML string for each JSON item, then .join("") combines them into one string ready to insert via innerHTML -- more concise than building elements individually, but requires manual escaping for any untrusted content.

Note: Reserve the template-literal-string approach specifically for JSON data you fully trust (like your own API), since it requires manual escaping otherwise.

Warning: Inserting a template-literal-built string containing untrusted, un-escaped user content via innerHTML is a real cross-site scripting (XSS) vulnerability.

Example: Building an HTML String with Template Literals

javascript
const items = [{ name: "Sam" }, { name: "Amit" }];
const html = items.map(item => `<li>${item.name}</li>`).join("");
document.body.innerHTML = `<ul>${html}</ul>`;

Handling an Empty JSON Array

A JSON response might legitimately contain an empty array -- rendering code should explicitly check for this and show a clear "no results" or "nothing here yet" message, rather than silently leaving a blank area that looks like a bug rather than an intentional empty state.

Note: Always add an explicit check for an empty array before or during rendering, showing a designed empty state rather than leaving a blank gap.

Warning: A blank area with no explanation, resulting from an unhandled empty array, is easy to mistake for a loading bug rather than a legitimate "there is nothing here" result.

Example: Handling an Empty JSON Array

javascript
const items = [];
document.body.innerHTML = items.length
  ? items.map(item => `<p>${item.name}</p>`).join("")
  : "<p>No results</p>";

Updating the DOM Efficiently on Data Changes

Rebuilding an entire list from scratch every time the underlying JSON data changes even slightly is wasteful -- for frequently-updating data, targeted updates (changing just the specific elements affected) or a lightweight diffing approach performs noticeably better than a full teardown-and-rebuild.

Note: For infrequent updates, a full rebuild is simple and perfectly fine; only optimize toward targeted updates once rebuild performance actually becomes a measurable problem.

Warning: Full-rebuild rendering on very frequent updates (like a live-updating feed) can cause visible flickering or lost UI state (like scroll position or focus) each time it redraws.

Example: Updating the DOM Efficiently on Data Changes

javascript
function updateItem(id, newText) {
  document.querySelector(`[data-id="${id}"]`).textContent = newText; // targeted update, not a full rebuild
}
console.log(typeof updateItem);

A Complete Fetch-to-HTML Example

Combining everything: fetching JSON, handling the loading and error states, checking for an empty result, and safely rendering the data as HTML -- the complete, realistic pipeline behind rendering almost any dynamic, data-driven section of a modern web page.

Note: Use this same complete pipeline shape -- fetch, loading state, error handling, empty check, safe render -- as the template for any new data-driven UI section you build.

Warning: Skipping any single step in this pipeline (especially error handling or the empty-state check) tends to surface later as a confusing edge-case bug rather than an immediately obvious one.

Example: A Complete Fetch-to-HTML Example

javascript
document.body.innerHTML = "<p>Loading...</p>";
fetch("items.php")
  .then(r => r.json())
  .then(items => {
    document.body.innerHTML = items.length
      ? items.map(i => `<p>${i.name}</p>`).join("")
      : "<p>No results</p>";
  })
  .catch(() => document.body.innerHTML = "<p>Failed to load</p>");
Common Mistakes
  1. Inserting JSON-derived text directly into innerHTML without escaping it, opening an XSS vulnerability if that data ever contains user-generated content with embedded HTML or script tags.
  2. Rebuilding the entire list from scratch on every small data update, when updating just the changed elements would be far more efficient.
  3. Forgetting to handle an empty array from the JSON response, leaving a blank area instead of a clear "no results" message.
Chapter Summary
  • JSON data is typically rendered into HTML by looping over it and either building DOM elements or an HTML string for each item.
  • Any JSON-derived text that could contain user-generated content should be inserted via textContent (or escaped) rather than raw innerHTML, to avoid XSS.
  • Template literals combined with .map().join("") are a common concise pattern for building an HTML string from an array of JSON objects.
Browser Support

Rendering fetched JSON as HTML uses only standard DOM methods, supported in every modern browser.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.