DEV Community

Cover image for Simplify Validation with Joi in Just 4 Steps 🚀
Abayomi Ogunnusi
Abayomi Ogunnusi

Posted on

Simplify Validation with Joi in Just 4 Steps 🚀

Say goodbye to long if-else validation blocks! With the Joi npm package, you can achieve clean and efficient validation in just 4 simple steps.

Before diving into the steps, let's see how validations can be written using if-else.

const validateCreateCareer = (req, res, next) => {
  const { title, description, teamType, location, skills, salary, jobLevel, postingDate, employmentType, experienceRequired, remote } = req.body;

  if (!title) {
    return res.status(400).json({ status: 'error', message: 'Title is required.' });
  }

  if (!description) {
    return res.status(400).json({ status: 'error', message: 'Description is required.' });
  }

  if (!teamType || !['Engineering', 'Marketing', 'Sales'].includes(teamType)) { // Example teamType values
    return res.status(400).json({ status: 'error', message: 'Invalid or missing teamType.' });
  }

  if (!Array.isArray(location) || location.some((loc) => typeof loc !== 'string')) {
    return res.status(400).json({ status: 'error', message: 'Location must be an array of strings.' });
  }

  if (!Array.isArray(skills) || skills.some((skill) => typeof skill !== 'string')) {
    return res.status(400).json({ status: 'error', message: 'Skills must be an array of strings.' });
  }

  if (salary !== undefined && typeof salary !== 'number') {
    return res.status(400).json({ status: 'error', message: 'Salary must be a number.' });
  }

  next(); // Proceed if all validations pass
};

export default validateCreateCareer;

Enter fullscreen mode Exit fullscreen mode

Drawbacks of if-else Validation

💣 Verbosity: The code becomes lengthy and repetitive.
💣 Error-Prone: Higher risk of missing edge cases or typos.
💣 Maintenance: Harder to maintain or extend as requirements grow.

Now let's look at the JOYOUS way

🛠️ Step 1: Install the Joi Package

Run the following command to install Joi:

npm i joi
Enter fullscreen mode Exit fullscreen mode

🛠️ Step 2: Configure Joi Validation Middleware
Create a reusable validation middleware to streamline your validation process:

import Joi from 'joi';
import { Request, Response, NextFunction } from 'express';

const validate = (schema: Joi.ObjectSchema<object>) => {
  return (req: Request, res: Response, next: NextFunction) => {
    const { error } = schema.validate(req.body);
    const valid = error == null;

    if (valid) {
      next();
    } else {
      const { details } = error;
      const message = details.map((i) => i.message).join(',');

      const newMessage = message.replace(/"/g, '');
      res.status(422).json({
        status: 'error',
        message: newMessage,
      });
    }
  };
}; 

export { validate };
Enter fullscreen mode Exit fullscreen mode

🛠️ Step 3: Create a Joi Validator File
Define your validation schemas in a dedicated file:

    createCareerSchema: Joi.object().keys({
        title: Joi.string().required(),
        description: Joi.string().required(),
        teamType: Joi.string().valid(...Object.values(TeamType)).required(),
        location: Joi.array().items(Joi.string()).required(),
        skills: Joi.array().items(Joi.string()).required(),
        salary: Joi.number(),
        jobLevel: Joi.string().valid("Junior", "Mid-Level", "Senior").required(),
        postingDate: Joi.date().iso().required(),
        employmentType: Joi.string().valid("Full-Time", "Part-Time", "Contract").required(),
        experienceRequired: Joi.number().integer().min(0).required(),
        remote: Joi.boolean().default(false),
    }),
};

export default careersSchema;
Enter fullscreen mode Exit fullscreen mode

🛠️ Step 4: Use It in Your Routes
Integrate the validation middleware in your Express routes:

import { validate } from './middleware/validate';
import careersSchema from './validators/careersSchema';
import CareersController from './controllers/CareersController';

router.patch(
  "/careers/:id/update", 
  validate(careersSchema.updateCareerSchema), 
  CareersController.updateCareer
);

router.post(
  "/careers", 
  validate(careersSchema.createCareerSchema), 
  CareersController.createCareer
);

export default router;
Enter fullscreen mode Exit fullscreen mode

✅ Test It Out!
Try making API requests with missing or invalid fields. The middleware will automatically handle errors and return a user-friendly response. 🎉

Image description

With these 4 steps, your validation process becomes concise, efficient, and easy to maintain. Happy coding! 🚀

Top comments (0)