Skip to content

Validate nested object properties in javascript

License

Notifications You must be signed in to change notification settings

WingmanImd/validate

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

validate

Validate object properties in javascript.

npm version Build Status Codecov

Usage

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.'

Custom error messages

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.'
    }
  }
})

Nesting

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.

Custom validators

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.`
})

Custom types

Pass a constructor to .type to validate against a custom type:

class Car {}

const user = new Schema({
  car: { type: Car }
})

Chainable API

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 }]})

Typecasting

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)
})

Property stripping

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.

API

Table of Contents

Property

A property instance gets returned whenever you call schema.path(). Properties are also created internally when an object is passed to the Schema constructor.

Parameters

  • name String the name of the property
  • schema Schema parent schema

message

Registers messages.

Parameters
Examples
prop.message('something is wrong')
prop.message({ required: 'thing is required.' })

Returns Property

schema

Mount given schema on current path.

Parameters
  • schema Schema the schema to mount
Examples
const user = new Schema({ email: String })
prop.schema(user)

Returns Property

use

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.

Parameters
  • fns Object object with named validation functions to call
Examples
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

required

Registers a validator that checks for presence.

Parameters
  • bool Boolean? true if required, false otherwise (optional, default true)
Examples
prop.required()

Returns Property

type

Registers a validator that checks if a value is of a given type

Parameters
Examples
prop.type(String)
prop.type('string')

Returns Property

length

Registers a validator that checks length.

Parameters
  • rules (Object | Number) object with .min and .max properties or a number
    • rules.min Number minimum length
    • rules.max Number maximum length
Examples
prop.length({ min: 8, max: 255 })
prop.length(10)

Returns Property

size

Registers a validator that checks size.

Parameters
  • rules (Object | Number) object with .min and .max properties or a number
    • rules.min Number minimum size
    • rules.max Number maximum size
Examples
prop.size({ min: 8, max: 255 })
prop.size(10)

Returns Property

enum

Registers a validator for enums.

Parameters
  • enums
  • rules Array allowed values
Examples
prop.enum(['cat', 'dog'])

Returns Property

match

Registers a validator that checks if a value matches given regexp.

Parameters
  • regexp RegExp regular expression to match
Examples
prop.match(/some\sregular\sexpression/)

Returns Property

each

Registers a validator that checks each value in an array against given rules.

Parameters
Examples
prop.each({ type: String })
prop.each([{ type: Number }])
prop.each({ things: [{ type: String }]})
prop.each(schema)

Returns Property

elements

Registers paths for array elements on the parent schema, with given array of rules.

Parameters
  • arr Array array of rules to use
Examples
prop.elements([{ type: String }, { type: Number }])

Returns Property

path

Proxy method for schema path. Makes chaining properties together easier.

Parameters
  • args ...any
Examples
schema
  .path('name').type(String).required()
  .path('email').type(String).required()

typecast

Typecast given value

Parameters
  • value Mixed value to typecast
Examples
prop.type(String)
prop.typecast(123) // => '123'

Returns Mixed

validate

Validate given value

Parameters
  • value Mixed value to validate
  • ctx Object the object containing the value
  • path String? path of the value being validated (optional, default this.name)
Examples
prop.type(Number)
assert(prop.validate(2) == null)
assert(prop.validate('hello world') instanceof Error)

Returns ValidationError

Schema

A Schema defines the structure that objects should be validated against.

Parameters

  • obj Object? schema definition (optional, default {})
  • opts Object? options (optional, default {})
    • opts.typecast Boolean typecast values before validation (optional, default false)
    • opts.strip Boolean strip properties not defined in the schema (optional, default true)

Examples

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]
})

path

Create or update path with given rules.

Parameters
Examples
const schema = new Schema()
schema.path('name.first', { type: String })
schema.path('name.last').type(String).required()

Returns Property

validate

Validate given obj.

Parameters
  • obj Object the object to validate
  • opts Object? options, see Schema (optional, default {})
Examples
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

Assert that given obj is valid.

Parameters
Examples
const schema = new Schema({ name: String })
schema.assert({ name: 1 }) // Throws an error

message

Override default error messages.

Parameters
  • name (String | Object) name of the validator or an object with name-message pairs
  • message (String | Function)? the message or message generator to use
Examples
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

validator

Override default validators.

Parameters
  • name (String | Object) name of the validator or an object with name-function pairs
  • fn Function? the function to use
Examples
schema.validator('required', val => val != null)
schema.validator({ required: val => val != null })

Returns Schema

typecaster

Override default typecasters.

Parameters
  • name (String | Object) name of the validator or an object with name-function pairs
  • fn Function? the function to use
Examples
schema.typecaster('SomeClass', val => new SomeClass(val))
schema.typecaster({ SomeClass: val => new SomeClass(val) })

Returns Schema

Licence

MIT

About

Validate nested object properties in javascript

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%