← 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.
Syntax
javascript
const object = JSON.parse(jsonText);
element.innerHTML = object.property;

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.

उदाहरण: 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.

उदाहरण: Building an HTML String with Template Literals

javascript
// Declare the constant `items`, set to `[{ name: "Sam" }, { name: "Amit" }]`
// Declare the constant `items`, set to `[{ name: "Sam" }, { name: "Amit" }]`
const items = [{ name: "Sam" }, { name: "Amit" }];
// Declare the constant `html`, set to `items.map(item => `<li>${item.name}</li>`).join("")`
// Declare the constant `html`, set to `items.map(item => `<li>${item.name}</li>`).join("")`
const html = items.map(item => `<li>${item.name}</li>`).join("");
// Assign `<ul>${html}</ul>` to `document.body.innerHTML`
// Assign `<ul>${html}</ul>` to `document.body.innerHTML`
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.

उदाहरण: Handling an Empty JSON Array

javascript
// Declare the constant `items`, set to `[]`
// Declare the constant `items`, set to `[]`
const items = [];
// Assign `items.length` to `document.body.innerHTML`
// Assign `items.length` to `document.body.innerHTML`
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.

उदाहरण: 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.

उदाहरण: A Complete Fetch-to-HTML Example

javascript
// Assign "<p>Loading...</p>" to `document.body.innerHTML`
// Assign "<p>Loading...</p>" to `document.body.innerHTML`
document.body.innerHTML = "<p>Loading...</p>";
// Define the method `fetch` taking `"items.php"`
// Define the method `fetch` taking `"items.php"`
fetch("items.php")
  // On success, run this with the resolved value as `r`
  // On success, run this with the resolved value as `r`
  .then(r => r.json())
  // On success, run this with the resolved value as `items`
  // On success, run this with the resolved value as `items`
  .then(items => {
    // Assign `items.length` to `document.body.innerHTML`
    // Assign `items.length` to `document.body.innerHTML`
    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>");
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}

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.