How to Fetch and Parse JSON Data from a Local File Using the Fetch API

Use the browser's native fetch() method with a relative file path, chain .then(response => response.json()) to deserialize the body, and consume the resulting JavaScript object in the next promise resolution.

The jisan-mia/dom-projects repository demonstrates a robust, production-ready pattern to fetch and parse JSON data from a local file using the fetch API. In the site's entry-point script, the application loads a static data.json file to hydrate the project list UI without requiring a backend server or external network requests.

The Core Implementation in index.js

The canonical implementation lives in index.js (lines 23–31). The fetchProjects function requests the local JSON asset, parses the response, and delegates rendering to renderProjectList.

// index.js
function fetchProjects() {
  fetch("./data.json")               // ① request the local file
    .then((res) => res.json())       // ② parse JSON into a JS object
    .then((projects) => {
      renderProjectList(projects);   // ③ render the UI
    })
    .catch((err) => console.log(err));
}

Key details from the source:

  • Relative URL: "./data.json" resolves to the same origin, avoiding CORS restrictions.
  • Promise chain: fetch returns a Response object; calling .json() returns a second promise that resolves to the parsed data.
  • Error boundary: The .catch() block prevents runtime crashes if the file is missing or malformed.

Step-by-Step Breakdown

1. Initiating the Request

The fetch function accepts a resource identifier. For local files served by the same web server, use a relative path.

fetch("./data.json")

According to the dom-projects source code, this pattern is used to load the static dataset that populates the homepage grid.

2. Parsing the Response Body

The Response object provides several body-reading methods. For JSON data, use response.json(), which reads the stream to completion and parses the text as JSON.

.then(response => response.json())

This method returns a promise that resolves to the actual JavaScript object or array defined in data.json.

3. Consuming the Data

Once parsed, the data can be passed to rendering functions or state management logic.

.then(projects => {
  // projects is the array from data.json
  renderProjectList(projects);
})

In the repository, renderProjectList iterates over the array to generate DOM nodes for each project card.

Complete Working Example

Below is a minimal, runnable HTML page that demonstrates the pattern isolated from the larger codebase.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Local JSON Fetch Demo</title>
</head>
<body>
  <h1>Projects</h1>
  <ul id="project-list"></ul>

  <script>
    // Fetch and parse JSON data from a local file using fetch API
    fetch("./data.json")
      .then(response => {
        if (!response.ok) {
          throw new Error(`HTTP error: ${response.status}`);
        }
        return response.json();
      })
      .then(data => {
        const list = document.getElementById("project-list");
        data.forEach(project => {
          const li = document.createElement("li");
          li.textContent = `${project.name}: ${project.description}`;
          list.appendChild(li);
        });
      })
      .catch(error => console.error("Fetch failed:", error));
  </script>
</body>
</html>

Place a data.json file in the same directory containing a valid JSON array to see the rendered output.

Reusable Helper Function

For larger applications like dom-projects, abstract the fetch-and-parse logic into a utility function to avoid repetition.

/**
 * Loads a local JSON file and returns the parsed data.
 * @param {string} path - Relative path to the JSON file.
 * @returns {Promise<any>} The parsed JSON content.
 */
function loadLocalJson(path) {
  return fetch(path)
    .then(response => {
      if (!response.ok) {
        throw new Error(`Failed to load ${path}: ${response.status} ${response.statusText}`);
      }
      return response.json();
    });
}

// Usage in the project context
loadLocalJson("./data.json")
  .then(projects => renderProjectList(projects))
  .catch(err => console.error("Project data unavailable:", err));

This pattern is consistent with the implementation found in index.js, where the fetch logic is encapsulated within fetchProjects but could be further generalized for multiple data sources.

Summary

  • Initiate the request with fetch("./data.json") using a relative path to avoid CORS issues.
  • Parse the response by calling .json() on the Response object to deserialize the JSON into a JavaScript object.
  • Handle errors with a .catch() block to manage missing files or network failures gracefully.
  • Reference implementation: The jisan-mia/dom-projects repository demonstrates this pattern in index.js (lines 23–31) to populate the project list from data.json.

Frequently Asked Questions

Can the Fetch API load local JSON files without a web server?

No. The Fetch API requires the resource to be served over HTTP/HTTPS. Opening an HTML file directly from the filesystem (file:// protocol) will cause CORS errors or silent failures in most modern browsers. You must serve the files via a local development server (e.g., npx serve, Live Server, or Python's http.server).

What is the difference between response.text() and response.json()?

response.text() reads the body stream and returns a promise that resolves to a raw string, which is useful for CSV or plain text files. response.json() is a convenience method that first reads the stream as text, then automatically calls JSON.parse() to convert the string into a JavaScript object or array. Use response.json() exclusively when consuming JSON data.

How do I handle CORS errors when fetching local JSON?

CORS errors occur when the JavaScript origin does not match the resource origin. For local files in the same project, ensure you use a relative path (e.g., "./data.json" or "data.json") rather than an absolute URL. Serve both the HTML and JSON from the same web server and port. If you control the server, ensure it sends the Access-Control-Allow-Origin header for cross-origin requests.

Why does my fetch request return undefined instead of JSON data?

This typically happens when you forget to return the promise from the .json() method or when you attempt to access the data outside the promise chain. Ensure you chain .then(response => response.json()) and place your logic that consumes the data inside the subsequent .then() block. The Fetch API is asynchronous; the data is not available immediately after the fetch() call.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →