Request body validations with Joi in ExpressJS application
Validation is a crucial part of any API server. However, validating for large request body can get cumbersome and can lead to doing too much in a controller.
In this article, we will see how we can add validations in an Express API.
Introducing Joi
Joi was originally built by Hapi.js team as a plugin to support object schema validation within the Hapi framework.
It provides body, query and URL params validation in Hapi.js. Adding validation is as simple as calling the right method. It also supports validation on deeply nested objects which most of the other validation modules out there don’t. Let’s have a look at an example from their GitHub page.
const Joi = require('joi');
const schema = Joi.object().keys({
username: Joi.string().alphanum().min(3).max(30).required(),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
access_token: [Joi.string(), Joi.number()],
birthyear: Joi.number().integer().min(1900).max(2013),
email: Joi.string().email()
}).with('username', 'birthyear').without('password', 'access_token');
// Return result.
const result = Joi.validate({ username: 'abc', birthyear: 1994 }, schema);
// result.error === null -> valid
// You can also pass a callback which will be called synchronously with the validation result.
Joi.validate({ username: 'abc', birthyear: 1994 }, schema, function (err, value) { }); // err === null -> valid
The above example can be explained as follows.
The above schema defines the following constraints:
- username
- a required string
- must contain only alphanumeric characters
- at least 3 characters long but no more than 30
- must be accompanied by birthyear
- password
- an optional string
- must satisfy the custom regex
- cannot appear together with access_token
- access_token
- an optional, unconstrained string or number
- birthyear
- an integer between 1900 and 2013
- email
- a valid email address string
Developers working with other frameworks realized the power and simplicity of this validation tool and worked on projects to support them. A project based on Joi also supports browsers.
Joi with Express
There are quite a few (at-least 3) projects that provide a middleware to add Joi based validations to express applications. I particularly like express-joi-validator, it’s simple to use and does the job pretty well.
Let’s see how we can use it.
Usage
First, we will have to install the package along with Joi.
Once installed require Joi and the middleware into our module.
const expressJoi = require('express-joi-validator');
For an ExpressJS application we can take user input via a url-param, query or in the req body. We can add validations on all these types with express-joi-validator. Joi provides us with all the validation functions and magic where as express-joi-validator is a middleware that helps us run it in an express application.
- Also see: Build REST APIs using Hapi.js
- Also see: Build REST APIs using ExpressJS
Let’s see how we can do validations for these types.
query: {
name: Joi.string().required()
},
body: {
age: Joi.number().required()
},
params: {
id: Joi.number().required()
}
}
If you see above we have added validations on all three ways a user can pass input. The query object validates for query parameters, the body object validates for inputs passed in request body and the params object validates for inputs from the URL. Now to protect an ExpressJS API, we will pass this schema to our middleware.
res.send('validated');
});
That’s it. It’s as easy as that.
Now a lot of people have trouble figuring out how to validate nested objects. So, here is an example.
query: {
name: Joi.string().required()
},
body: {
age: Joi.number().required(),
company: Joi.object({
name: Joi.string().required(),
role: Joi.string().required().valid('HR', 'Technical') //enum style validation
}).required()
},
params: {
id: Joi.number().required()
}
}
Added a company object to the body.
The last thing we need to do is, add error handling. And this is how we do it.
app.use(function (err, req, res, next) {
if (err.isBoom) {
return res.status(err.output.statusCode).json(err.output.payload);
}
});
Example
Here is an example ExpressJS API with validations.
const express = require('express');
const bodyParser = require('body-parser');
const Joi = require('joi');
const expressJoi = require('express-joi-validator');
var app = express();
app.use(bodyParser.json());
const schema = {
query: {
name: Joi.string().required()
},
body: {
age: Joi.number().required(),
company: Joi.object({
name: Joi.string().required(),
role: Joi.string().required().valid('HR', 'Technical') //enum style validation
}).required()
},
params: {
id: Joi.number().required()
}
}
app.post('/testapi/:id', expressJoi(schema), function(req, res){
res.send('validated');
});
//error handler
app.use(function (err, req, res, next) {
if (err.isBoom) {
return res.status(err.output.statusCode).json(err.output.payload);
}
});
app.listen('3000', ()=>{
console.log(`listening to 3000`);
});
Conclusion
Thus in this article, we learned a neat and easy way to validate APIs in Node.js and ExpressJS using Joi validator. Joi as a package can also be used independently and hence can be used for any Node.js API validations not just for expressjs or hapi.js
Keep Learning…
Don’t stop here… We have more learning stuff for you.
7 comments
Leave a Comment
greate post! may i translate this post to korean?
sure.
Hi Shaik, thanks for the great info on joi validations. I am looking for setting custom messages when the validation fails with joi. Do you have any idea on that?
sir , please you share with me , how I will give validation in angularjs Application
It was helpfull for me, thanks!
very clean way
This tutorial is really useful. I have used it with form validation in Expressjs middleware. It works well. and I have got the best way from these tutorials. So, Thanks for sharing the knowledge.