express.js middleware for validating requests against JSON Schema
Coming from express-jsonschema
? Read our migration notes
Major version 1.x
of this module uses ajv@5
, read their changelog and migration guide here.
Major version 2.x
uses ajv@6
in order to support draft-07 of JSON Schema.
Please keep in mind that you have to manually configure ajv to support draft-06 schema files from now on (see https://github.com/epoberezkin/ajv#using-version-6).
Why use this library over express-jsonschema ?
- Performance - ajv offers a significant performance boost over JSONSchema.
- Latest JSON Schema Standard - ajv supports JSON Schema v7 proposal.
- Active Maintenance -
express-json-validator-middleware
is being actively maintained.
- 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.
npm install express-json-validator-middleware
or
yarn add express-json-validator-middleware
--save
is no longer necessary as of npm@5
- Require the module
const { Validator, ValidationError } = require('express-json-validator-middleware');
- Initialize a Validator instance, optionally passing in an ajv#options object
const validator = new Validator({allErrors: true});
- Optional - Define a bound shortcut function that can be used instead of Validator.validate
const validate = validator.validate;
- Use the Validator.validate method as an Express middleware, passing in an options object of the following format:
Validator.validate({
requestProperty: schemaToUse
});
Example: Validate req.body
against bodySchema
app.post('/street/', validate({body: bodySchema}), function(req, res) {
// route code
});
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
const express = require('express');
const { Validator, ValidationError } = require('express-json-validator-middleware');
// Initialize a Validator instance first
const validator = new Validator({allErrors: true}); // pass in options to the Ajv instance
// Define a shortcut function
const validate = validator.validate;
// Define a JSON Schema
const StreetSchema = {
type: 'object',
required: ['number', 'name', 'type'],
properties: {
number: {
type: 'number'
},
name: {
type: 'string'
},
type: {
type: 'string',
enum: ['Street', 'Avenue', 'Boulevard']
}
}
};
const app = express();
app.use(express.json());
// 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
// execute your route code
res.send('valid');
});
// Error handler for validation errors
app.use(function(err, req, res, next) {
if (err instanceof ValidationError) {
// At this point you can execute your error handling code
res.status(400).send('invalid');
next();
} else {
next(err); // pass error on if not a validation error
}
});
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.
const TokenSchema = {
type: 'object', // req.query is of type object
required: ['token'], // req.query.token is required
properties: {
uuid: { // validate token
type: 'string',
format: 'uuid',
minLength: 36,
maxLength: 36
}
}
};
app.post('/street/', Validator.validate({body: StreetSchema, query: TokenSchema}), function(req, res) {
// application code
});
A valid request must now include a token URL query. Example valid URL: /street/?uuid=af3996d0-0e8b-4165-ae97-fdc0823be417
Instead of passing in a schema object you can also pass in a function that will return a schema. It is useful if you need to generate or alter the schema based on the request object.
Example: loading schema from the database
// Middleware executed before validate function
function loadSchema(req, res, next) {
getSchemaFromDB()
.then((schema) => {
req.schema = schema;
next();
})
.catch(next);
}
// function that returns a schema object
function getSchema(req) {
// return the schema from the previous middleware or the default schema
return req.schema || DefaultSchema;
}
app.post('/street/', loadSchema, Validator.validate({body: getSchema}), function(req, res) {
// route code
});
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
Ajv must be configured before you call Validator.validate()
to add middleware. (e.g. if you need to define custom keywords
Tests are written using Mocha & Chai
npm install
npm test
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
}
}
}
- Maintained by @simonplend
- Created and previously maintained by @vacekj
- Thank you to all of this project's contributors
- Based on the express-json-schema library by @trainiac