donut imageCodenut.dev
Blog
About
Portfolio
published: November 9, 2023
Article author picture
Kain NhantumboWeb Developer & Designer
Share:
Read: 3 minutesWords: 908Characters: 6288

Schema Validation with Zod and Express.js

Security

They say “Never trust user input” - I know that this may sound extreme, but it is an important security principle in programming. Today, we will learn together how to implement Zod in a Express.js application.

Table of Contents

  • Understanding schema validation
  • The need for validation library
  • What is Zod?
  • Why do we need Zod?
  • Why do we need to validate API Calls?
  • Final thoughts

This article will explain the concept of schema validation, explore the features of Zod, and demonstrate Zod validation, and its usage to ensure robust data integrity in Express applications.

Proper schema validation can help to prevent errors, improve performance, and ensure data security.

Understanding schema validation

Schema validation is the process of verifying that incoming data conforms to a set of predefined rules or specifications, known as a schema.This is used to ensure the quality of data, to prevent errors, and to improve the performance of applications. So, validation is particularly crucial when dealing with user inputs, API responses, or any external data source and typically encompass a range of criteria, like as shown below:

  • Data types: Specifying the expected type of data, such as strings, numbers, booleans, arrays, objects, etc.
  • Format constraints: Defining rules for the format of data, such as valid email addresses, phone numbers, dates, and more.
  • Structure: Ensuring the correct structure of nested objects, arrays, and their respective properties.
  • Validation conditions: Specifying conditions under which data is considered valid or invalid.

The need for validation library

What is Zod?

Zod is, according to its documentation, a TypeScript-first schema declaration and validation library, Created by Colin McDonnell. Unlike Yup, Zod is TypeScript-first which means it has a lot of features for TypeScript developers.

Zod comes with some really great features like:

  • Works in Node.js and browsers (including IE 11)
  • Zero dependencies
  • Works with JavaScript too
  • Static type inference: Zod can automatically infer the TypeScript type of a data structure based on its schema.

Zod provides a declarative way to define and validate data schemas using a clean and intuitive syntax. Zod is heavily influenced by TypeScript’s type system, which makes it particularly appealing to TypeScript developers.

Why do we need Zod?

Some developers might reason, Why we need Zod when we are already using Typescript. Well, Typescript helps with static type checking, but it only does this at compile time. After the build process, the type safety of Typescript disappears and Zod solves this problem.

With Zod, you can create a schema and use it to verify form inputs and user input at runtime.

Why do we need to validate API Calls?

API Calls validation helps you getting the right data that you want. For example, you want your users to have a strong password(e.g. at least 6 characters), you can use something like Zod or Yup and prevent users from entering a short password(less than 6 characters). Also, doing validation on the server makes your server much more secure, because no one can open the developer tools, go through your code and figure out how to beat your validation.

Let's dive in with a practical examples:

First, go and create an empty directory and navigate into it:

bash
1mkdir schema-validation-with-zod-and-expressjs
2cd schema-validation-with-zod-and-expressjs

Then, initialize a Node.js project and add the necessary dependencies:

bash
1npm init -y
2npm install express zod

Next, add the following script to our package.json file.

json
1{
2  // ...
3  "scripts": {
4    "dev": "node app.js"
5  }
6  // ...
7}

Now let's start an Express.js server. Create a file called app.js at the root of the project:

js
1const express = require('express');
2
3const app = express();
4
5app.use(express.json());
6
7app.listen(8080, () => console.log(`Ready on http://localhost:${8080}`));

Then run the Express.js server (you can access it at http://localhost:8080).

bash
1npm run dev

Next, we can start working with Zod. Let's first import z from zod and add a simple login schema.

js
1const express = require('express');
2const { z } = require('zod');
3
4const app = express();
5
6app.use(express.json());
7
8const LoginSchema = z.object({
9  // In this example we will only validate the request body.
10  body: z.object({
11    email: z.string().email(),
12    password: z.string().min(6)
13  })
14});

Now we are going to create our middleware for Zod validation.

js
1// ...
2
3const validate = (schema) => (req, res, next) => {
4  try {
5    schema.parse({
6      body: req.body,
7      query: req.query,
8      params: req.params
9    });
10
11    next();
12  } catch (err) {
13    return res.status(400).send(err.errors);
14  }
15};
16
17// ...

Finally, we are going to create a route(/login) for POST requests, which we will use our validate middleware to perform the validation of the request body.

js
1// ...
2
3// pass LoginSchema to validate middleware
4app.post('/login', validate(LoginSchema), (req, res) => {
5  return res.json({ ...req.body });
6});
7
8// ...

The final code would be as follows:

js
1const express = require('express');
2const { z } = require('zod');
3
4const app = express();
5
6app.use(express.json());
7
8const LoginSchema = z.object({
9  // In this example we will only validate the request body.
10  body: z.object({
11    // email should be valid
12    email: z.string().email(),
13    // password should be at least 6 characters
14    password: z.string().min(6)
15  })
16});
17
18const validate = (schema) => (req, res, next) => {
19  try {
20    schema.parse({
21      body: req.body,
22      query: req.query,
23      params: req.params
24    });
25
26    next();
27  } catch (err) {
28    return res.status(400).send(err.errors);
29  }
30};
31
32app.post('/login', validate(LoginSchema), (req, res) => {
33  return res.json({ ...req.body });
34});
35
36app.listen(8080, () => console.log(`> Ready on http://localhost:${8080}`));

Final thoughts

Schema validation is a critical part of any software development process, ensuring data integrity and consistency.

Zod provides a simple and powerful solution for schema validation in TypeScript projects. With its intuitive syntax, built-in validation rules, and support for custom validation, Zod makes it easy to define and validate data structures.

When using Zod for schema validation, developers can reduce errors, improve code quality, and build more robust applications

In this guide, We learned how to validate our Express.js REST API Calls using Zod.

I hope this article helped you understanding how schema validation works. See yaa!

Get in touch

Donuts combo decoration image

Crafted with ❤ using Next.js and Typescript.

© 2025 Kain NhantumboVersion 6.3.0-09-2024