JSON and the Server

JSON becomes truly useful once it starts moving between the browser and a server — this lesson covers fetching JSON, sending it back with POST, and handling the responses correctly.

JSON as the Language of the Web

Most modern web applications are really just two programs talking to each other over HTTP: a client running in the browser and a server running somewhere else. JSON is the format they agree to speak. When your JavaScript code needs a list of products, a user's profile, or the result of a search, it almost always asks a server for that data as JSON, and when it needs to save something, it usually sends JSON back.

Fetching JSON with fetch()

The fetch() function is the standard way to make HTTP requests from JavaScript. It returns a Promise that resolves to a Response object. That Response object represents the raw HTTP response — to get usable data out of it, you call .json(), which itself returns a Promise that resolves to a parsed JavaScript value.

Fetching a JSON resource

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p id="demo"></p>

<script>
async function loadUser(id) {
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  console.log(user.name, user.email);
  return user;
}

loadUser(42);
</script>

</body>
</html>

Sending JSON to a Server

To send JSON, you configure fetch() with a method other than the default GET, a body, and a header that tells the server what kind of data is in that body. JavaScript objects are not sent directly — they must be converted to a JSON string first with JSON.stringify(), because HTTP bodies are just text, not live objects.

Sending JSON with POST

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p id="demo"></p>

<script>
async function createUser(data) {
  const response = await fetch('/api/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  });
  return response.json();
}

createUser({ name: 'Priya', email: 'priya@example.com' });
</script>

</body>
</html>
  • The client builds a JavaScript object and converts it with JSON.stringify().
  • fetch() sends the string as the HTTP request body, along with a Content-Type: application/json header.
  • The server reads the raw request body and parses it back into a native data structure.
  • The server does its work (saves to a database, runs a calculation, etc.) and builds a response value.
  • The server encodes that response as a JSON string and sends it back with its own Content-Type: application/json header.
  • The client calls response.json() to turn the reply back into a usable JavaScript value.

Handling Errors Properly

A common mistake is assuming fetch() rejects when the server returns an error status like 404 or 500. It does not — fetch() only rejects on network failures such as no connection, a DNS failure, or a CORS block. A 404 or 500 response is still a 'successful' fetch as far as the Promise is concerned, so you must check response.ok or response.status yourself.

Checking response status before parsing

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p id="demo"></p>

<script>
async function safeLoad(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`Server responded with ${response.status}`);
    }
    return await response.json();
  } catch (err) {
    console.error('Failed to load data:', err.message);
    return null;
  }
}
</script>

</body>
</html>
AspectGETPOST
PurposeRetrieve existing dataCreate or submit new data
BodyNoneJSON payload via JSON.stringify()
IdempotentYes — safe to repeatNo — repeating can create duplicates
Typical responseJSON representing a resourceJSON confirming what was created
Note: Prefer async/await over chained .then() calls once a sequence has more than one step — it reads top-to-bottom like ordinary code and makes try/catch error handling straightforward.
Note: If you forget the 'Content-Type': 'application/json' header, many server frameworks won't parse the body as JSON at all, even though the bytes you sent are perfectly valid JSON — the request body will show up as empty or undefined on the server.

Exercise: JSON and the Server

When a browser requests data from a server, in what form does JSON typically travel?