Work with JSON data and make HTTP requests using the Fetch API for communicating with web services.
JSON (JavaScript Object Notation) is a lightweight text format for data exchange. It is the most common format for sending and receiving data from web APIs.
Converting between JS and JSON:
// JavaScript object to JSON string
const user = { name: 'Alice', age: 30 };
const jsonString = JSON.stringify(user);
console.log(jsonString); // '{"name":"Alice","age":30}'
// JSON string to JavaScript object
const parsed = JSON.parse(jsonString);
console.log(parsed.name); // 'Alice'Pretty-printing JSON with indentation:
JSON.stringify(user, null, 2);
// {
// "name": "Alice",
// "age": 30
// }Key differences from JavaScript objects:
"name", not name)undefined (use null instead){
"name": "Alice",
"scores": [95, 87, 92],
"active": true,
"address": null
}The Fetch API provides a modern way to make HTTP requests from JavaScript. It replaces the older XMLHttpRequest.
// Basic GET request
const response = await fetch('https://api.example.com/users');
const data = await response.json();
console.log(data);Key points about fetch:
fetch(url) returns a Promise that resolves to a Response objectresponse.ok — true if status is 200-299response.status — the HTTP status code (200, 404, 500, etc.)response.headers — the response headersParsing the response body:
// Parse as JSON
const json = await response.json();
// Parse as plain text
const text = await response.text();
// Parse as binary (Blob)
const blob = await response.blob();Important: Each body parsing method (json(), text(), etc.) can only be called once per response. The body stream is consumed after the first call.
By default, fetch() makes a GET request. You can make other types of requests by passing an options object.
POST request (sending data):
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Alice',
email: 'alice@example.com',
}),
});
const newUser = await response.json();Other HTTP methods:
// PUT — replace entire resource
await fetch('/api/users/1', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice', age: 31 }),
});
// PATCH — partial update
await fetch('/api/users/1', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ age: 31 }),
});
// DELETE
await fetch('/api/users/1', { method: 'DELETE' });Custom headers:
const response = await fetch('/api/data', {
headers: {
'Authorization': 'Bearer my-token',
'Accept': 'application/json',
},
});A common mistake is assuming fetch() throws on HTTP errors. It does not.
fetch() only rejects the Promise on network failures (no internet, DNS error, etc.). A 404 or 500 response is still a successful fetch — you must check manually.
try {
const response = await fetch('/api/data');
// Check if the HTTP status indicates success
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
// Catches both network errors AND our thrown error
console.error('Request failed:', error.message);
}Creating a reusable wrapper:
async function fetchJSON(url, options = {}) {
const response = await fetch(url, {
headers: { 'Content-Type': 'application/json' },
...options,
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
// Usage
try {
const users = await fetchJSON('/api/users');
console.log(users);
} catch (err) {
console.error(err.message);
}This pattern ensures you handle both network errors and HTTP error responses in one place.
<div id="output"></div>
<script>
// JSON.stringify and JSON.parse
const product = {
name: 'Laptop',
price: 999.99,
specs: { ram: '16GB', storage: '512GB' }
};
// Convert to JSON string
const json = JSON.stringify(product, null, 2);
// Parse back to object
const parsed = JSON.parse(json);
// Simulate a fetch-like flow with JSON data
const mockApiResponse = JSON.stringify({
status: 'success',
data: { users: ['Alice', 'Bob', 'Charlie'] }
});
const apiData = JSON.parse(mockApiResponse);
const output = document.getElementById('output');
output.innerHTML = `
<p><strong>Original:</strong> ${product.name} - $${product.price}</p>
<p><strong>JSON:</strong></p>
<pre>${json}</pre>
<p><strong>Parsed specs:</strong> ${parsed.specs.ram}, ${parsed.specs.storage}</p>
<p><strong>API users:</strong> ${apiData.data.users.join(', ')}</p>
`;
</script>What does response.json() return?