The Codex / Technologies / Express.js / Validation

Validation

Never trusting request data - validating request bodies with Zod, the express-validator alternative, and returning useful error messages.

What it is, in plain English: Validation means checking that incoming request data (body, query, params) matches what your route handler expects before acting on it -- correct types, required fields present, values within acceptable ranges. Without validation, malformed or malicious input can crash your server, corrupt your database, or open security holes. Zod is the most popular modern choice for Express APIs -- it defines a schema once and uses it for both validation and TypeScript types.

Never trusting what arrives in a request

The golden rule: validate everything from the client. Request bodies, query strings, and route parameters can contain anything -- missing fields, wrong types, malicious content. Always validate before using them.

What happens without validation

// Looks fine until someone sends bad data:
app.post("/users", (req, res) => {
  const user = createUser(req.body.name, req.body.email, req.body.age);
  res.status(201).json(user);
});

// What if req.body.age is the string "twenty" instead of a number?
// What if req.body.email is missing entirely?
// What if req.body.name is 10,000 characters long?
// Without validation, your server either crashes or silently stores bad data.

Validation with Zod -- the modern standard

// npm install zod
import { z } from "zod";

const userSchema = z.object({
  name:  z.string().min(1, "Name is required").max(100),
  email: z.string().email("Must be a valid email address"),
  age:   z.number().int().min(0).max(150),
});

app.post("/users", (req, res) => {
  const result = userSchema.safeParse(req.body);

  if (!result.success) {
    return res.status(400).json({ errors: result.error.issues });
  }

  // result.data is now guaranteed valid AND correctly typed:
  const user = createUser(result.data);
  res.status(201).json(user);
});

Common schema building blocks

z.string()                          // must be a string
z.string().min(3).max(50)           // length constraints
z.string().email()                  // must look like an email
z.string().url()                    // must be a valid URL
z.number().int().positive()         // whole positive numbers only
z.boolean()                          // true/false
z.enum(["admin", "user", "guest"])  // must be one of these exact values
z.array(z.string())                  // an array of strings
z.string().optional()                // field can be omitted
z.string().default("guest")          // fills in a default if omitted
Try It Yourself (Node.js logic)

Official Sources

The Codex links only to official documentation. No third-party tutorials.