Asynchronous JS, APIs, and JSON
Fetch and process data asynchronously, design and consume APIs, and add realtime features.
Content
JSON parsing and schemas
Versions:
Watch & Learn
AI-discovered learning video
Sign in to watch the learning video for this topic.
JSON parsing and schemas — practical patterns for CS50 Web
You've already danced with Promises and strutted with async/await. Now meet the wardrobe that clothes your data: JSON parsing and schemas.
You're coming off topics like Promises chaining and errors and Async/await patterns, so I won't re-teach you how to await a fetch. Instead: how to safely turn that network blob into something your app trusts, how to validate it, and how to avoid injecting sketchy JSON into the DOM like it's a mystery meat sandwich.
Why JSON parsing and schemas matter (quick refresher)
- JSON is the standard lingua franca for APIs. You fetch it; you parse it; you hope it's what you expected.
- Parsing is turning a JSON string into a JS object: the moment the network becomes usable.
- Schemas are contracts that say what shape that object should be. No schema → surprise undefineds, runtime bugs, and angry users.
This builds directly on async/await: you await response.json() to parse, but parsing without validation is like trusting every Tinder profile. Always verify.
The right way to parse JSON from fetch
Micro explanation: use response.ok, check content-type, and handle parse failures.
// typical pattern with async/await
async function getData(url) {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const contentType = response.headers.get('content-type') || '';
if (!contentType.includes('application/json')) {
throw new Error('Expected JSON response');
}
// This might throw if the body isn't valid JSON
const data = await response.json();
return data;
}
Why these steps? Because response.json() can throw if the body is malformed; and some APIs may return HTML error pages (dangerous if you assume JSON). Always check status and content-type first.
Parse errors and graceful fallback
- Wrap your parse in try/catch.
- Provide user-friendly feedback.
- Log enough to debug but not leak secrets.
try {
const data = await getData('/api/profile');
// then validate schema before using
} catch (err) {
console.error('Fetch/parse error:', err);
showUserMessage('Sorry, we couldn\'t load your data. Try again.');
}
Basic manual validation (for small schemas)
When the schema is simple, don't reach for a heavy library yet. Write explicit checks.
// Example JSON we expect:
// { id: 123, name: 'Ava', roles: ['student', 'admin'] }
function validateUser(obj) {
if (!obj || typeof obj !== 'object') return false;
if (typeof obj.id !== 'number') return false;
if (typeof obj.name !== 'string') return false;
if (!Array.isArray(obj.roles)) return false;
if (!obj.roles.every(r => typeof r === 'string')) return false;
return true;
}
// usage
const user = await getData('/api/user');
if (!validateUser(user)) throw new Error('Invalid user schema');
Micro explanation: explicit checks are verbose but clear. They fail fast and are easy to debug.
JSON Schema: formalizing the contract
When your API grows, a formal schema is worth it. JSON Schema (draft) is a popular standard. You can write a schema and use a validator like AJV in Node/browser.
Example schema for the user object above:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "name", "roles"],
"additionalProperties": false,
"properties": {
"id": {"type": "number"},
"name": {"type": "string"},
"roles": {"type": "array", "items": {"type": "string"}}
}
}
And validating with AJV (Node/browser):
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(userSchema);
if (!validate(user)) {
console.warn(validate.errors);
throw new Error('Schema validation failed');
}
Why use JSON Schema? Reuse, auto-generated docs, and consistent validation across client/server.
Nested objects, optional fields, and defaults
- Use
requiredfor must-haves; omit for optional. - Use
nullable(or atype: ["string","null"]) if null is allowed. - To give defaults, set them server-side or use a post-parse step in JS:
const safeUser = {
id: user.id,
name: user.name ?? 'Guest', // nullish coalescing
roles: user.roles ?? []
};
Security & DOM: never trust unvalidated JSON
If you used "JavaScript Essentials and the DOM" to learn DOM insertion, remember:
- Insert untrusted text with element.textContent, not innerHTML.
- When creating markup from JSON (like comments), sanitize or use safe templates.
Bad:
el.innerHTML = user.description; // if description contains <script>, you're fried
Good:
el.textContent = user.description;
// or build elements and set attributes via DOM methods
Debugging tips and common gotchas
- Unexpected types: use console.assert(typeof x === 'string').
- Extra fields: use schema's
additionalProperties: falseto surface them. - Arrays of mixed types: JSON can't carry type metadata — you must validate items.
- Large payloads: consider streaming/parsing incrementally or paginating.
Quote to remember:
"This is the moment where the concept finally clicks." — when your schema catches a bug before a user does.
Quick checklist before using JSON data in your app
- Check response.ok and headers
- Try parsing with response.json() inside try/catch
- Validate shape (manual checks or JSON Schema)
- Apply defaults and transformations
- Insert into DOM safely (textContent or templates)
- Log validation errors for debugging
Key takeaways (TL;DR)
- Parsing is easy; trusting parsed data responsibly is the skill. Use content-type checks, try/catch, and validation.
- For small shapes, manual validation is fine; for growing APIs, use JSON Schema + a validator like AJV.
- Always sanitize before touching the DOM — prefer textContent over innerHTML.
- This all ties to what you learned about Promises and async/await: parsing and validation are the next steps after
await response.json().
Final little brain tickler: schemas are your app's immune system. They catch the bugs that would otherwise cause the whole body to feverishly misbehave.
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!