Introduction to Joi validation in Node.js Express

Abbas Aslanbay
4 min readJan 8, 2023

--

Node.js Express

Joi is an object schema validation library for Node.js. It allows you to create simple and complex validation schemas for your application’s data. In this tutorial, we will learn how to use Joi in a Node.js Express application to validate request body, params, and query.

Setting up the project

First, let’s create a new Node.js project and install the required dependencies:

$ mkdir my-project
$ cd my-project
$ npm init -y
$ npm install express joi

Next, create an index.js file and add the following code to it:

const express = require('express');
const app = express();
const port = 3000;

app.listen(port, () => console.log(`Listening on port ${port}`));

This will create a simple express server that listens on port 3000.

Validation middleware

Let’s create a middleware function that will validate the request body using Joi. Add the following code to the index.js file:

const express = require('express');
const app = express();
const Joi = require('joi');

const port = 3000;

const validateRequest = (schema) => {
return (req, res, next) => {
const result = Joi.validate(req.body, schema);
if (result.error) {
return res.status(400).json({
error: result.error.details[0].message,
});
}
if (!req.value) {
req.value = {};
}
req.value['body'] = result.value;
next();
};
};

app.listen(port, () => console.log(`Listening on port ${port}`));

This middleware function takes a validation schema as an argument and applies it to the request body. If the request body is invalid, it sends a 400 Bad Request response with an error message. If the request body is valid, it adds the validated value to the req.value.body property and calls the next middleware function.

Validation schema

Now let’s create a validation schema for the request body. Add the following code to the index.js file:

const express = require('express');
const app = express();
const Joi = require('joi');

const port = 3000;

const schema = Joi.object().keys({
email: Joi.string().email().required(),
password: Joi.string().min(8).required(),
});

const validateRequest = (schema) => {
return (req, res, next) => {
const result = Joi.validate(req.body, schema);
if (result.error) {
return res.status(400).json({
error: result.error.details[0].message,
});
}
if (!req.value) {
req.value = {};
}
req.value['body'] = result.value;
}
}
app.listen(port, () => console.log(`Listening on port ${port}`));

Here is the rest of the article:

Using the middleware

Now that we have the validation middleware and schema set up, let’s use them in a route. Add the following code to the index.js file:

app.post('/signup', validateRequest(schema), (req, res) => {
res.json({
message: 'Successfully signed up!',
data: req.value.body,
});
});

This creates a POST route at /signup that uses the validation middleware and schema we created earlier. If the request body is valid, it will return a success message and the validated request body data.

Testing the route

Let’s test the /signup route using Postman or a similar tool. Make a POST request to http://localhost:3000/signup with the following JSON in the request body:

{
"email": "invalidemail",
"password": "short"
}

You should receive a 400 Bad Request response with an error message.

Now try making a POST request with the following JSON in the request body:

{
"email": "valid@email.com",
"password": "longenough"
}

You should receive a 200 OK response with a success message and the validated request body data.

Validating params and query

In addition to the request body, you can also validate the request params and query using the same technique. Here is an example of how to do it:

const schema = Joi.object().keys({
id: Joi.string().alphanum().required(),
});

app.put('/user/:id', validateRequest(schema), (req, res) => {
res.json({
message: 'Successfully updated user!',
data: req.value.body,
});
});

app.get('/user', validateRequest(schema), (req, res) => {
res.json({
message: 'Successfully retrieved user!',
data: req.value.query,
});
});

This creates a PUT route that validates the id param using the validation schema, and a GET route that validates the query using the same schema.

Conclusion

In this tutorial, we learned how to use Joi validation in a Node.js Express application to validate request body, params, and query. Validation is an important aspect of any application, and using a library like Joi makes it easy to set up and maintain.

Here is a full example of using Joi validation in a Node.js Express application:

const express = require('express');
const app = express();
const Joi = require('joi');

const port = 3000;

const validateRequest = (schema) => {
return (req, res, next) => {
const result = Joi.validate(req.body, schema);
if (result.error) {
return res.status(400).json({
error: result.error.details[0].message,
});
}
if (!req.value) {
req.value = {};
}
req.value['body'] = result.value;
next();
};
};

const signupSchema = Joi.object().keys({
email: Joi.string().email().required(),
password: Joi.string().min(8).required(),
});

app.post('/signup', validateRequest(signupSchema), (req, res) => {
res.json({
message: 'Successfully signed up!',
data: req.value.body,
});
});

const userSchema = Joi.object().keys({
id: Joi.string().alphanum().required(),
});

app.put('/user/:id', validateRequest(userSchema), (req, res) => {
res.json({
message: 'Successfully updated user!',
data: req.value.body,
});
});

app.get('/user', validateRequest(userSchema), (req, res) => {
res.json({
message: 'Successfully retrieved user!',
data: req.value.query,
});
});

app.listen(port, () => console.log(`Listening on port ${port}`));

This example defines two validation schemas: signupSchema and userSchema. It also defines three routes: a POST route for signing up, a PUT route for updating a user, and a GET route for retrieving a user. Each of these routes uses the validateRequest middleware to apply the appropriate validation schema to the request.

--

--