Introduction to Joi validation in 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.