express-json-validator-middleware
express.js middleware for validating requests against JSON Schema
Coming from express-jsonschema
? Read our migration notes
Starting with 1.1.0
, this module uses ajv@5
, read their changelog and migration guide here.
express-jsonschema ?
Why use this library over- Performance - ajv offers a significant performance boost over JSONSchema.
- Latest JSON Schema Standard - ajv supports JSON Schema v6 proposal.
- Active Maintenance -
express-json-validator-middleware
is being actively maintained.
Why validate with JSON schemas?
- Simple - JSON schemas are a simple and expressive way to describe a data structure.
- Standard - JSON schemas are not specific to Javascript. In fact, they are used just about everywhere.
- Fail-Fast - Catch errors early in your logic, evading confusing errors later.
- Separate Validation - Keep your routes clean. Validation logic doesn't need to be defined in your route handlers.
- Error Messaging - Ajv provides you with rich error objects that can easily be transformed into human-readable format.
- Documentation - Creating a JSON Schema is another way of documenting your application.
Installation
$ npm install express-json-validator-middleware
--save
is no longer necessary as of npm@5
Getting started
- Install the module
- Require the module
var { Validator, ValidationError } = require('express-json-validator-middleware');
- Initialize a Validator instance, optionally passing in an ajv#options object
var validator = new Validator({allErrors: true});
- Optional - Define a shortcut function.
var validate = validator.validate;
- Use the function as an Express middleware, passing in an options object of the following format:
validate({
request_property: schema_to_use
})
Example: Validate req.body against BodySchema
app.post('/street/', validate({body: BodySchema}), function(req, res) {
// route code
});
Error handling
On encountering erroneous data, the validator will call next() with a ValidationError object. It is recommended to setup a general error handler for your app where you will catch ValidationError errors
Example - error thrown for the body
request property
ValidationError {
name: 'JsonSchemaValidationError',
validationErrors: {
body: [AjvError]
}
}
More information on ajv#errors
Example Express app
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var { Validator, ValidationError } = require('express-json-validator-middleware');
// Initialize a Validator instance first
var validator = new Validator({allErrors: true}); // pass in options to the Ajv instance
// Define a shortcut. It is perfectly okay to use validator.validate() as middleware, this just makes it easier
var validate = validator.validate;
// Define a JSON Schema
var StreetSchema = {
type: 'object',
required: ['number', 'name', 'type'],
properties: {
number: {
type: 'number'
},
name: {
type: 'string'
},
type: {
type: 'string',
enum: ['Street', 'Avenue', 'Boulevard']
}
}
}
// This route validates req.body against the StreetSchema
app.post('/street/', validate({body: StreetSchema}), function(req, res) {
// At this point req.body has been validated and you can
// begin to execute your application code
});
Validating multiple request properties
Sometimes your route may depend on the body
and query
both having a specific format. In this example we use body
and query
but you can choose to validate any request
properties you like.
var TokenSchema = {
type: 'object', // req.query is of type object
required: ['token'] // req.query.token is required
properties: {
token: { // validate token
type: 'string',
format: 'alphanumeric',
minLength: 10,
maxLength: 10
}
}
}
app.post('/street/', validate({body: StreetSchema, query: TokenSchema}), function(req, res) {
// application code
});
Using dynamic schema
Instead of passing schema object you can also pass a function that will return a schema. It is useful if you need to generate or alter the schema based of Request object.
Example: loading schema from the database
function loadSchema(req, res, next) {
getSchemaFromDB()
.then((schema) => {
req.schema = schema;
next();
})
.catch((err) => next(err));
}
function getSchema(req) {
return req.schema || DefaultSchema;
}
app.post('/street/', loadSchema, validate({body: getSchema}), function(req, res) {
// route code
});
A valid request must now include a token URL query. Example valid URL: /street/?token=F42G5N5BGC
Custom keywords
Ajv custom keywords must be defined before any validate() middleware
Example:
var { Validator, ValidationError } = require('express-json-validator-middleware');
var validator = new Validator({allErrors: true});
validator.ajv.addKeyword('constant', { validate: function (schema, data) {
return typeof schema == 'object' && schema !== null
? deepEqual(schema, data)
: schema === data;
}, errors: false });
// route handlers with validate()
More info on custom keywords: ajv#customs-keywords
Ajv instance
The Ajv instance can be accessed via validator.ajv.
var { Validator, ValidationError } = require('express-json-validator-middleware');
var validator = new Validator({allErrors: true});
validator.ajv // ajv instance
Tests
Tests are written using Mocha & Chai
npm install
npm test
More documentation on JSON schemas
Migrating from express-jsonschema
In express-jsonschema
, you could define a required property in two ways. Ajv only supports one way of doing this.
// CORRECT
{
type: 'object',
properties: {
foo: {
type: 'string'
},
required: ['foo'] // <-- correct way
}
}
// WRONG
{
type: 'object',
properties: {
foo: {
type: 'string',
required: true // nono way
}
}
}
Credits
- Maintained by @JouzaLoL
- Original Module by @trainiac
- PRs: