DEV Community

Cover image for Schema Validation with Zod and Express.js
Imad Atyat-Allah
Imad Atyat-Allah

Posted on • Updated on

Schema Validation with Zod and Express.js

This guide was originally published on my personal portfolio

What is Zod?

Zod is 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

Why do you need to validate your API Calls?

Validating your API Calls 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 start coding

First, Create an empty directory and navigate into it:

mkdir schema-validation-with-zod-and-expressjs
cd schema-validation-with-zod-and-expressjs
Enter fullscreen mode Exit fullscreen mode

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

npm init -y
npm install express zod
Enter fullscreen mode Exit fullscreen mode

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

{
  // ...
  "scripts": {
    "dev": "node index.js"
  }
  // ...
}
Enter fullscreen mode Exit fullscreen mode

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

const express = require("express");

const app = express();

app.use(express.json());

app.listen(1337, () => console.log(`> Ready on http://localhost:${1337}`));
Enter fullscreen mode Exit fullscreen mode

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

npm run dev
Enter fullscreen mode Exit fullscreen mode

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

const express = require("express");
const { z } = require("zod");

const app = express();

app.use(express.json());

const LoginSchema = z.object({
  // In this example we will only validate the request body.
  body: z.object({
    // email should be valid and non-empty
    email: z.string().email(),
    // password should be atleast 6 characters
    password: z.string().min(6),
  }),
});

// ...
Enter fullscreen mode Exit fullscreen mode

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

// ...

const validate = (schema) => (req, res, next) => {
  try {
    schema.parse({
      body: req.body,
      query: req.query,
      params: req.params,
    });

    next();
  } catch (err) {
    return res.status(400).send(err.errors);
  }
};

// ...
Enter fullscreen mode Exit fullscreen mode

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

// ...

// pass LoginSchema to validate middleware
app.post("/login", validate(LoginSchema), (req, res) => {
  return res.json({ ...req.body });
});

// ...
Enter fullscreen mode Exit fullscreen mode

The final code would be as follows:

const express = require("express");
const { z } = require("zod");

const app = express();

app.use(express.json());

const LoginSchema = z.object({
  // In this example we will only validate the request body.
  body: z.object({
    // email should be valid and non-empty
    email: z.string().email(),
    // password should be atleast 6 characters
    password: z.string().min(6),
  }),
});

const validate = (schema) => (req, res, next) => {
  try {
    schema.parse({
      body: req.body,
      query: req.query,
      params: req.params,
    });

    next();
  } catch (err) {
    return res.status(400).send(err.errors);
  }
};

app.post("/login", validate(LoginSchema), (req, res) => {
  return res.json({ ...req.body });
});

app.listen(1337, () => console.log(`> Ready on http://localhost:${1337}`));
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this guide, We learned how to validate our Express.js REST API Calls using Zod, You can find the code on GitHub.

Make sure to contact me if you have any questions.

Oldest comments (1)

Collapse
 
andresvanegas19 profile image
andresvanegas19 • Edited

Great articule.

For future readers, the nonempty methos is now deprecated.

If you want to implement it, just need to replace like:

z.string({
   required_error: "Name is required",
   invalid_type_error: "Name must be a string",
})
Enter fullscreen mode Exit fullscreen mode

From the documentation: zod.dev/?id=strings