Skip to main content
Version: Next

checkSchema()

checkSchema()

checkSchema(schema: Schema, defaultLocations?: Location[]): ValidationChain[] & ContextRunner

Creates a list of validation chains based on the provided schema, which can then be passed to an express.js route for validation.

app.post(
'/signup',
checkSchema({
email: { isEmail: true },
password: { isLength: { options: { min: 8 } } },
}),
(req, res) => {
// Handle request
},
);

By default, all specified fields are validated in all request locations (all of body, cookies, headers, params and query).
This list can be changed by specifying the defaultLocations parameter. For example, to validate fields by default in body and query:

checkSchema(schema, ['body', 'query']);

You can also fine tune the locations checked for each field by setting the in property, which takes precedence over the defaultLocations parameter.

Manually running checkSchema()

checkSchema() returns a middleware, which makes it ideal to pass to an express.js route. But since it also implements the ContextRunner interface, you can also run it manually, if you wish.

app.post('/signup', async (req, res) => {
const result = await checkSchema({
email: { isEmail: true },
password: { isLength: { options: { min: 8 } } },
}).run(req);

if (!result.isEmpty()) {
console.log('Failed validation');
}
});
tip

Schema

The schema is a simple object from field paths to field schemas. The field paths define which fields get selected for validation, and the schema defines how those fields get validated.

A field schema is an object whose keys can be a mix of one or more of

If the object keys are none of the above, then it has to be a custom schema.

Built-in Validators

Any of the built-in validators can be used in a field schema.

If the built-in validator is set to true, then it's turned on without any options:

checkSchema() usage
checkSchema({
email: { isEmail: true },
password: { notEmpty: true },
});
Validation chain equivalent
check('email').isEmail();
check('password').notEmpty();

The value may also be an object, in which case the validator is turned on with additional configurations:

options

Sets the options of the validator. If there are multiple options, then options must be an array. Otherwise, you can pass the value directly.

checkSchema() usage
checkSchema({
phone: {
isMobilePhone: {
options: ['any', { strictMode: true }],
},
},
password: {
isLength: {
options: { min: 8 },
},
},
});
Validation chain equivalent
check('phone').isMobilePhone('any', {
strictMode: true,
});
check('password').isLength({ min: 8 });
note

If the only option to be passed to the validator is an array, then it must be wrapped in another array. This is usually the case of isIn; for example:

checkSchema({
weekend: {
// 👎 Translates to `isIn('saturday', 'sunday')`
isIn: { options: ['saturday', 'sunday'] },
// 👍 Translates to `isIn(['saturday', 'sunday'])`
isIn: { options: [['saturday', 'sunday']] },
},
});

bail

Stop running the validation chain if the current validator (or any of the previous validators) failed. Equivalent to using .bail() on a validation chain.

checkSchema() usage
checkSchema({
email: {
// isEmail is run first. If the email isn't valid, then the
// custom validator `checkEmailNotInUse` won't run
isEmail: { bail: true },
custom: { options: checkEmailNotInUse },
},
});
Validation chain equivalent
check('email').isEmail().bail().custom(checkEmailNotInUse);

if

Adds a condition on whether the field's validators should continue running. Equivalent to using .if() on a validation chain.

if is applied before the current validator. This means that if its condition isn't met, then that validator and following validators won't run.

checkSchema({
newPassword: {
exists: {
// With a custom validator
if: (value, { req }) => !!req.body.oldPassword,

// With a validation chain
if: body('oldPassword').notEmpty(),
},
},
});

negated

Negates the validator. Equivalent to using .not() on a validation chain.

checkSchema({
password: {
// Check if password is not empty
isEmpty: { negated: true },
},
});

errorMessage

Sets the error message for a validator. Equivalent to using .withMessage() on a validation chain.

checkSchema() usage
checkSchema({
email: {
isEmail: {
errorMessage: 'Must be a valid e-mail address',
},
},
});
Validation chain equivalent
check('email').isEmail().withMessage('Must be a valid e-mail address');

Built-in Sanitizers

Any of the built-in sanitizers can be used in a field schema.

If the built-in sanitizer is set to true, then it's turned on without any options:

checkSchema() usage
checkSchema({
query: { trim: true },
});
Validation chain equivalent
check('query').trim();

The value may also be an object, in which case the sanitizer is turned on with additional configurations:

options

Sets the options of the sanitizer. If there are multiple options, then options must be an array. Otherwise, you can pass the value directly.

checkSchema() usage
checkSchema({
email: {
normalizeEmail: {
options: { gmail_remove_subaddress: true },
},
},
});
Validation chain equivalent
check('email').normalizeEmail({
gmail_remove_subaddress: true,
});

Field schema modifiers

The following properties can be specified in the schema of a field to modify its general behavior:

in

Defines the location(s) in which to validate the field. To validate that a field exists in either the body or in the query string, the following schema can be written:

checkSchema({
field: {
in: ['body', 'query'],
exists: true,
},
});

errorMessage

Sets the default error message for the field's validators.
Used when a validator doesn't specify errorMessage in its own configurations.

checkSchema() usage
checkSchema({
password: {
errorMessage: 'The password must be at least 8 characters, and must contain a symbol',
isLength: { options: { min: 8 } },
matches: { options: /[-_$#]/ },
},
});
Validation chain equivalent
check('password', 'The password must be at least 8 characters, and must contain a symbol')
.isLength({ min: 8 })
.matches(/[-_$#]/);

optional

Sets the optional modifier on the field. Equivalent to using .optional() on a validation chain.

checkSchema() usage
checkSchema({
query: {
optional: true,
isLength: { options: { min: 3 } },
},
});
Validation chain equivalent
check('query').optional().isLength({ min: 3 });

Custom validators/sanitizers

There are two ways of defining custom validators or sanitizers using checkSchema().

The first way is to set custom or customSanitizer in a field's schema. These work exactly like any other validator or sanitizer in the schema:

checkSchema() usage
checkSchema({
email: {
custom: {
options: checkIfEmailExists,
bail: true,
},
customSanitizer: {
options: removeEmailAttribute,
},
},
});
Validation chain equivalent
check('email').custom(checkIfEmailExists).bail().customSanitizer(removeEmailAttribute);

While this works fine, it's only possible to set a single custom validator/sanitizer when using schemas. The reason for this is simple: objects in JavaScript cannot have duplicated keys (well, they can, but only the last one will apply).

For this reason, it's possible to use multiple custom validators/sanitizers in checkSchema() by setting in the field schema a key which isn't any of the built-in validators, sanitizers or modifiers.
These keys must be an object with a single custom or customSanitizer function.

The previous example can be rewritten like this:

checkSchema({
email: {
emailNotInUse: {
custom: checkEmailNotInUse,
bail: true,
},
removeEmailAttribute: {
customSanitizer: removeEmailAttribute,
},
},
});
info

The name of the custom validator/sanitizer is not used by checkSchema(). Different schemas can make use of the same custom name without clash.