JSON in Express.js — Request Parsing, Response Formatting, and Validation
Express.js has built-in support for JSON through its express.json() middleware and res.json() response helper. Setting up JSON parsing correctly is one of the first things you do when building an Express API.
Enabling JSON body parsing
Register express.json() as middleware before your routes. Without it, req.body will be undefined for JSON request bodies.
import express from "express";
const app = express();
// Must be registered before routes that read req.body
app.use(express.json());
app.post("/users", (req, res) => {
console.log(req.body); // parsed JSON object
res.status(201).json({ created: true });
});
app.listen(3000);Sending JSON responses
Use res.json() to send a JSON response. It sets Content-Type: application/json and calls JSON.stringify() for you.
app.get("/users/:id", async (req, res) => {
const user = await db.findUser(req.params.id);
if (!user) {
return res.status(404).json({ error: "User not found" });
}
res.json(user); // 200 OK with JSON body
// For arrays:
// res.json([user1, user2]);
});Accessing nested JSON fields from req.body
Once express.json() is registered, req.body is a fully-parsed JavaScript object. Access nested fields with dot notation or destructuring.
app.post("/orders", (req, res) => {
const { customerId, items, shipping } = req.body;
// Access nested fields
const city = req.body.shipping?.address?.city;
// Guard against missing fields
if (!customerId || !Array.isArray(items)) {
return res.status(400).json({ error: "Missing required fields" });
}
res.status(201).json({ orderId: "ord_123", customerId });
});Validating JSON with Zod
Always validate req.body before using it. Zod is a popular choice that works well with TypeScript — parse the body and return a 422 on validation failure.
import { z } from "zod";
const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().min(0).optional(),
});
app.post("/users", (req, res) => {
const result = CreateUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({
error: "Validation failed",
issues: result.error.issues,
});
}
const user = result.data; // typed: { name: string; email: string; age?: number }
res.status(201).json({ id: 1, ...user });
});Handling JSON parse errors
When a client sends malformed JSON, express.json() throws a SyntaxError. Catch it with an Express error middleware (4-argument function) placed after your routes.
import { ErrorRequestHandler } from "express";
const jsonErrorHandler: ErrorRequestHandler = (err, req, res, next) => {
if (err instanceof SyntaxError && "body" in err) {
return res.status(400).json({
error: "Invalid JSON",
message: err.message,
});
}
next(err);
};
// Register AFTER all routes
app.use(jsonErrorHandler);
// Generic error handler
app.use((err: Error, req, res, next) => {
console.error(err);
res.status(500).json({ error: "Internal server error" });
});Related Tools
Frequently Asked Questions
How do I parse JSON request bodies in Express?▾
Add app.use(express.json()) before your routes. This registers middleware that parses incoming requests with Content-Type: application/json and populates req.body with the parsed object.
Why is req.body undefined in my Express route?▾
You likely forgot to register express.json() middleware, or registered it after your route definition. Middleware runs in the order it is registered — make sure app.use(express.json()) comes before your route handlers.
How do I send a JSON response in Express?▾
Use res.json(data). It automatically sets Content-Type: application/json, serialises the value, and ends the response. Chain res.status(code).json(data) to set a non-200 status code.
How do I validate JSON in Express?▾
Use Zod with safeParse(): const result = schema.safeParse(req.body). If result.success is false, return a 400/422 with result.error.issues. Alternatives include Joi, express-validator, and Yup.
How do I handle malformed JSON in Express?▾
Add a 4-argument error middleware after your routes: (err, req, res, next) => { if (err instanceof SyntaxError && 'body' in err) return res.status(400).json({ error: 'Invalid JSON' }); next(err); }.
JSON in Other Languages
Format and validate your JSON instantly
Free, no ads, no sign-up. Also converts JSON to TypeScript, YAML, CSV, and more.
Open JSON Formatter →If jsondecode.com saved you time, share it with your team
Free forever. No ads. No sign-up. Help other developers find it.