Validate object properties in javascript.
Define a schema and call .validate()
with the object you want to validate.
The .validate()
function returns an array of validation errors.
import Schema from 'validate'
const user = new Schema({
username: {
type: String,
required: true,
length: { min: 3, max: 32 }
},
pets: [{
name: {
type: String
required: true
},
animal: {
type: String
enum: ['cat', 'dog', 'cow']
}
}],
address: {
street: {
type: String,
required: true
},
city: {
type: String,
required: true
}
zip: {
type: String,
match: /^[0-9]+$/,
required: true
}
}
})
const errors = user.validate(obj)
Each error has a .path
, describing the full path of the property that failed validation, and a .message
describing the error.
errors[0].path //=> 'address.street'
errors[0].message //=> 'address.street is required.'
You can override the default error messages by passing an object to Schema#message()
.
const post = new Schema({
title: { required: true }
})
post.message({
required: (path) => `${path} can not be empty.`
})
const [error] = post.validate({})
assert(error.message = 'title can not be empty.')
It is also possible to define messages for individual properties:
const post = new Schema({
title: {
required: true,
message: 'Title is required.'
}
})
And for individual validators:
const post = new Schema({
title: {
type: String,
required: true,
message: {
type: 'Title must be a string.',
required: 'Title is required.'
}
}
})
Objects and arrays can be nested as deep as you want:
const event = new Schema({
title: {
type: String,
required: true
},
participants: [{
name: String,
email: {
type: String,
required: true
},
things: [{
name: String,
amount: Number
}]
}]
})
Arrays can be defined implicitly, like in the above example, or explicitly:
const post = new Schema({
keywords: {
type: Array,
each: { type: String }
}
})
Array elements can also be defined individually:
const user = new Schema({
something: {
type: Array,
elements: [
{ type: Number },
{ type: String }
]
}
})
Nesting also works with schemas:
const user = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
}
})
const post = new Schema({
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},
author: user
})
If you think it should work, it probably works.
Validate will naively assume that a nested object where all property names are validators is not a nested object.
const schema = new Schema({
pet: {
type: {
required: true,
type: String,
enum: ['cat', 'dog']
}
}
});
In this example, the pet.type
property will be interpreted as a type
rule, and the validations will not work as intended. To work around this we could use the slightly more verbose properties
rule:
const schema = new Schema({
pet: {
properties: {
type: {
required: true,
type: String,
enum: ['cat', 'dog']
}
}
}
});
In this case the type
property of pets.properties
will be interpreted as a nested property, and the validations will work as intended.
Custom validators can be defined by passing an object with named validators to .use
:
const hexColor = val => /^#[0-9a-fA-F]$/.test(val)
const car = new Schema({
color: {
type: String,
use: { hexColor }
}
})
Define a custom error message for the validator:
car.message({
hexColor: path => `${path} must be a valid color.`
})
Pass a constructor to .type
to validate against a custom type:
class Car {}
const user = new Schema({
car: { type: Car }
})
If you want to avoid constructing large objects, you can add paths to a schema by using the chainable API:
const user = new Schema()
user
.path('username').type(String).required()
.path('address.zip').type(String).required()
Array elements can be defined by using $
as a placeholder for indices:
const user = new Schema()
user.path('pets.$').type(String)
This is equivalent to writing
const user = new Schema({ pets: [{ type: String }]})
Values can be automatically typecast before validation.
To enable typecasting, pass an options object to the Schema
constructor with typecast
set to true
.
const user = new Schema(definition, { typecast: true })
You can override this setting by passing an option to .validate()
.
user.validate(obj, { typecast: false })
To typecast custom types, you can register a typecaster:
class Car {}
const user = new Schema({
car: { type: Car }
})
user.typecaster({
Car: (val) => new Car(val)
})
By default, all values not defined in the schema will be stripped from the object.
Set .strip = false
on the options object to disable this behavior. This will likely be changed in a future version.
When strict mode is enabled, properties that are not defined in the schema will trigger a validation error. Set .strict = true
on the options object to enable strict mode.
- Property
- Schema
A property instance gets returned whenever you call schema.path()
.
Properties are also created internally when an object is passed to the Schema constructor.
Registers messages.
prop.message('something is wrong')
prop.message({ required: 'thing is required.' })
Returns Property
Mount given schema
on current path.
schema
Schema the schema to mount
const user = new Schema({ email: String })
prop.schema(user)
Returns Property
Validate using named functions from the given object.
Error messages can be defined by providing an object with
named error messages/generators to schema.message()
The message generator receives the value being validated, the object it belongs to and any additional arguments.
fns
Object object with named validation functions to call
const schema = new Schema()
const prop = schema.path('some.path')
schema.message({
binary: (path, ctx) => `${path} must be binary.`,
bits: (path, ctx, bits) => `${path} must be ${bits}-bit`
})
prop.use({
binary: (val, ctx) => /^[01]+$/i.test(val),
bits: [(val, ctx, bits) => val.length == bits, 32]
})
Returns Property
Registers a validator that checks for presence.
bool
Boolean?true
if required,false
otherwise (optional, defaulttrue
)
prop.required()
Returns Property
Registers a validator that checks if a value is of a given type
prop.type(String)
prop.type('string')
Returns Property
Convenience method for setting type to String
prop.string()
Returns Property
Convenience method for setting type to Number
prop.number()
Returns Property
Convenience method for setting type to Array
prop.array()
Returns Property
Convenience method for setting type to Date
prop.date()
Returns Property
Registers a validator that checks length.
prop.length({ min: 8, max: 255 })
prop.length(10)
Returns Property
Registers a validator that checks size.
prop.size({ min: 8, max: 255 })
prop.size(10)
Returns Property
Registers a validator for enums.
enums
rules
Array allowed values
prop.enum(['cat', 'dog'])
Returns Property
Registers a validator that checks if a value matches given regexp
.
regexp
RegExp regular expression to match
prop.match(/some\sregular\sexpression/)
Returns Property
Registers a validator that checks each value in an array against given rules
.
prop.each({ type: String })
prop.each([{ type: Number }])
prop.each({ things: [{ type: String }]})
prop.each(schema)
Returns Property
Registers paths for array elements on the parent schema, with given array of rules.
arr
Array array of rules to use
prop.elements([{ type: String }, { type: Number }])
Returns Property
Registers all properties from the given object as nested properties
props
Object properties with rules
prop.properties({
name: String,
email: String
})
Returns Property
Proxy method for schema path. Makes chaining properties together easier.
args
...any
schema
.path('name').type(String).required()
.path('email').type(String).required()
Typecast given value
value
Mixed value to typecast
prop.type(String)
prop.typecast(123) // => '123'
Returns Mixed
Validate given value
value
Mixed value to validatectx
Object the object containing the valuepath
String? path of the value being validated (optional, defaultthis.name
)
prop.type(Number)
assert(prop.validate(2) == null)
assert(prop.validate('hello world') instanceof Error)
Returns ValidationError
A Schema defines the structure that objects should be validated against.
const post = new Schema({
title: {
type: String,
required: true,
length: { min: 1, max: 255 }
},
content: {
type: String,
required: true
},
published: {
type: Date,
required: true
},
keywords: [{ type: String }]
})
const author = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
posts: [post]
})
Create or update path
with given rules
.
path
String full path using dot-notationrules
(Object | Array | String | Schema | Property)? rules to apply
const schema = new Schema()
schema.path('name.first', { type: String })
schema.path('name.last').type(String).required()
Returns Property
Validate given obj
.
const schema = new Schema({ name: { required: true }})
const errors = schema.validate({})
assert(errors.length == 1)
assert(errors[0].message == 'name is required')
assert(errors[0].path == 'name')
Returns Array
Assert that given obj
is valid.
const schema = new Schema({ name: String })
schema.assert({ name: 1 }) // Throws an error
Override default error messages.
name
(String | Object) name of the validator or an object with name-message pairsmessage
(String | Function)? the message or message generator to use
const hex = (val) => /^0x[0-9a-f]+$/.test(val)
schema.path('some.path').use({ hex })
schema.message('hex', path => `${path} must be hexadecimal`)
schema.message({ hex: path => `${path} must be hexadecimal` })
Returns Schema
Override default validators.
name
(String | Object) name of the validator or an object with name-function pairsfn
Function? the function to use
schema.validator('required', val => val != null)
schema.validator({ required: val => val != null })
Returns Schema
Override default typecasters.
name
(String | Object) name of the validator or an object with name-function pairsfn
Function? the function to use
schema.typecaster('SomeClass', val => new SomeClass(val))
schema.typecaster({ SomeClass: val => new SomeClass(val) })
Returns Schema
MIT