Written by: Geoffrey Callaghan

joi tutorial

Joi Tutorial

Joi is a powerful schema description language and data validator for JavaScript. It is often used for validating data in applications, especially in backend services built with Node.js. Here’s a step-by-step tutorial to help you get started with Joi.

Step 1: Install Joi

You can install Joi using npm or yarn:

npm install joi
# or
yarn add joi

Step 2: Basic Usage of Joi

To get started with Joi, let’s create a simple validation schema for an object with a name and an email.

  1. Create a basic validation schema:
const Joi = require('joi');

const schema = Joi.object({
  name: Joi.string()
    .required()
    .max(15)
    .messages({
      'string.empty': 'Name is required',
      'string.max': 'Name must be 15 characters or less'
    }),
  email: Joi.string()
    .email({ tlds: { allow: false } })
    .required()
    .messages({
      'string.empty': 'Email is required',
      'string.email': 'Invalid email address'
    })
});
  1. Validate data using the schema:
const data = {
  name: 'John Doe',
  email: 'johndoe@example.com'
};

const { error, value } = schema.validate(data);

if (error) {
  console.log('Validation failed:', error.details);
} else {
  console.log('Validation succeeded:', value);
}

Step 3: Advanced Validation with Joi

Joi can handle more complex validation scenarios, such as nested objects, arrays, and custom validation methods.

Nested Objects

const schema = Joi.object({
  user: Joi.object({
    name: Joi.string().required().messages({ 'string.empty': 'Name is required' }),
    email: Joi.string().email({ tlds: { allow: false } }).required().messages({ 'string.empty': 'Email is required', 'string.email': 'Invalid email address' })
  })
});

const data = {
  user: {
    name: 'John Doe',
    email: 'johndoe@example.com'
  }
};

const { error, value } = schema.validate(data);

if (error) {
  console.log('Validation failed:', error.details);
} else {
  console.log('Validation succeeded:', value);
}

Arrays

const schema = Joi.object({
  friends: Joi.array().items(
    Joi.object({
      name: Joi.string().required().messages({ 'string.empty': 'Name is required' }),
      email: Joi.string().email({ tlds: { allow: false } }).required().messages({ 'string.empty': 'Email is required', 'string.email': 'Invalid email address' })
    })
  )
});

const data = {
  friends: [
    { name: 'Jane Doe', email: 'janedoe@example.com' },
    { name: 'John Smith', email: 'johnsmith@example.com' }
  ]
};

const { error, value } = schema.validate(data);

if (error) {
  console.log('Validation failed:', error.details);
} else {
  console.log('Validation succeeded:', value);
}

Conditional Validation

const schema = Joi.object({
  isRequired: Joi.boolean(),
  value: Joi.string().when('isRequired', {
    is: true,
    then: Joi.string().required().messages({ 'string.empty': 'Value is required' }),
    otherwise: Joi.string()
  })
});

const data = { isRequired: true, value: '' };

const { error, value } = schema.validate(data);

if (error) {
  console.log('Validation failed:', error.details);
} else {
  console.log('Validation succeeded:', value);
}

Custom Validation

const schema = Joi.object({
  username: Joi.string().custom((value, helpers) => {
    if (value === 'admin') {
      return helpers.message('Username cannot be "admin"');
    }
    return value;
  })
});

const data = { username: 'admin' };

const { error, value } = schema.validate(data);

if (error) {
  console.log('Validation failed:', error.details);
} else {
  console.log('Validation succeeded:', value);
}

Step 4: Integrating Joi with Express

Joi is often used in conjunction with Express for validating request data.

  1. Set up an Express application:
npm install express
# or
yarn add express
  1. Create a basic Express server with Joi validation:
const express = require('express');
const Joi = require('joi');

const app = express();
app.use(express.json());

const schema = Joi.object({
  name: Joi.string().required().max(15).messages({
    'string.empty': 'Name is required',
    'string.max': 'Name must be 15 characters or less'
  }),
  email: Joi.string().email({ tlds: { allow: false } }).required().messages({
    'string.empty': 'Email is required',
    'string.email': 'Invalid email address'
  })
});

app.post('/signup', (req, res) => {
  const { error, value } = schema.validate(req.body);
  
  if (error) {
    return res.status(400).json({ error: error.details[0].message });
  }
  
  res.status(200).json({ message: 'Validation succeeded', data: value });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Conclusion

Joi is a versatile and powerful library for schema validation in JavaScript applications. It offers a comprehensive set of features for validating complex data structures and integrates seamlessly with backend frameworks like Express. This tutorial covers the basics, but Joi offers much more functionality that you can explore in its official documentation.