This notebook introduces Joi, a powerful schema validation library for JavaScript. We'll explore how to use Joi to validate objects, forms, API payloads, and configuration data with simple, readable validation rules.
$ npm install joi added 6 packages in 7s 28 packages are looking for funding run `npm fund` for details
Joi version: 17.13.3
Let's start with some basic validation examples to understand how Joi works. Joi allows you to define schemas that describe the shape of your data.
Valid user validation result: { value: { username: 'johndoe', email: 'john@example.com', birthYear: 1990, password: 'password123' } }
Invalid user validation result: { value: { username: 'j', email: 'not-an-email', birthYear: 1800, password: 'pw' }, error: [Error [ValidationError]: "username" length must be at least 3 characters long] { _original: { username: 'j', email: 'not-an-email', birthYear: 1800, password: 'pw' }, details: [ [Object] ] } }
Joi provides several options to customize the validation behavior.
Strict validation (default): { value: { name: 'Jane Smith', age: 28, email: 'jane@example.com', favoriteColor: 'blue', address: { street: '123 Main St', city: 'Anytown', zipCode: '12345', country: 'USA' } }, error: [Error [ValidationError]: "address.country" is not allowed] { _original: { name: 'Jane Smith', age: 28, email: 'jane@example.com', favoriteColor: 'blue', address: [Object] }, details: [ [Object] ] } }
Validation with allowUnknown: true: { value: { name: 'Jane Smith', age: 28, email: 'jane@example.com', favoriteColor: 'blue', address: { street: '123 Main St', city: 'Anytown', zipCode: '12345', country: 'USA' } } }
Validation with stripUnknown: true: { value: { name: 'Jane Smith', age: 28, email: 'jane@example.com', address: { street: '123 Main St', city: 'Anytown', zipCode: '12345' } } }
Validation with abortEarly: true (default): { value: { username: 'j', email: 'not-an-email', birthYear: 1800, password: 'pw' }, error: [Error [ValidationError]: "name" is required] { _original: { username: 'j', email: 'not-an-email', birthYear: 1800, password: 'pw' }, details: [ [Object] ] } } Validation with abortEarly: false: { value: { username: 'j', email: 'not-an-email', birthYear: 1800, password: 'pw' }, error: [Error [ValidationError]: "name" is required. "email" must be a valid email. "username" is not allowed. "birthYear" is not allowed. "password" is not allowed] { _original: { username: 'j', email: 'not-an-email', birthYear: 1800, password: 'pw' }, details: [ [Object], [Object], [Object], [Object], [Object] ] } }
Joi provides a rich set of validation rules for different data types.
Joi allows you to create schemas with conditional validation logic.
Personal account validation result: { value: { username: 'johndoe', password: 'password123', accountType: 'personal' } }
Business account validation result: { value: { username: 'acmecorp', password: 'securepass123', accountType: 'business', companyName: 'ACME Corporation', taxId: '123-45-6789' } }
Invalid business account validation result: { value: { username: 'acmecorp', password: 'securepass123', accountType: 'business' }, error: [Error [ValidationError]: "companyName" is required. "taxId" is required] { _original: { username: 'acmecorp', password: 'securepass123', accountType: 'business' }, details: [ [Object], [Object] ] } }
Joi allows you to customize error messages for better user experience.
Signup validation with custom messages: { value: { username: 'a', email: 'not-an-email', password: 'weak' }, error: [Error [ValidationError]: Username must be at least 3 characters long. Please enter a valid email address. Password must be at least 8 characters long. Password must contain at least one uppercase letter, one lowercase letter, and one number] { _original: { username: 'a', email: 'not-an-email', password: 'weak' }, details: [ [Object], [Object], [Object], [Object] ] } }
Formatted errors for UI display: { username: 'Username must be at least 3 characters long', email: 'Please enter a valid email address', password: 'Password must contain at least one uppercase letter, one lowercase letter, and one number' }
Let's see how Joi can be used to validate API requests in a real-world scenario.
Validated API request: { query: { page: 2, limit: 20, sort: 'desc', filter: 'published' }, body: { title: 'Understanding Joi Validation', content: 'Joi is a powerful schema validation library for JavaScript...', tags: [ 'javascript', 'validation', 'nodejs' ], published: true, authorId: '507f1f77bcf86cd799439011' }, params: { id: '507f1f77bcf86cd799439011' }, headers: { 'content-type': 'application/json', authorization: 'Bearer token123' } }
Invalid API request validation result: [ { message: '"page" must be greater than or equal to 1', path: [ 'page' ], type: 'number.min', context: { limit: 1, value: 0, label: 'page', key: 'page' } }, { message: '"limit" must be less than or equal to 100', path: [ 'limit' ], type: 'number.max', context: { limit: 100, value: 200, label: 'limit', key: 'limit' } }, { message: '"sort" must be one of [asc, desc]', path: [ 'sort' ], type: 'any.only', context: { valids: [Array], label: 'sort', value: 'invalid', key: 'sort' } } ]
Joi is great for validating environment variables and configuration objects.
Validated environment configuration: { NODE_ENV: 'production', PORT: 8080, DATABASE_URL: 'mongodb://localhost:27017/myapp', API_KEY: 'secret-api-key-123', LOG_LEVEL: 'warn', ENABLE_CACHE: true, CORS_ORIGINS: [ 'example.com', 'api.example.com' ], CACHE_TTL: 300 } ENABLE_CACHE type: boolean CACHE_TTL (default): 300
Joi allows you to create custom validation functions for complex validation logic.
Valid order validation result: { value: { customerId: 'cust123', items: [ [Object], [Object] ], total: 46.97 } }
Invalid order validation result: { value: { customerId: 'cust123', items: [ [Object], [Object] ], total: 50 }, error: [Error [ValidationError]: Error code "order.invalidTotal" is not defined, your custom type is missing the correct messages definition] { _original: { customerId: 'cust123', items: [Array], total: 50 }, details: [ [Object] ] } }
Let's look at some performance considerations when using Joi.
Here are some practical tips for using Joi effectively in your projects.
Reusable schema components: { type: 'object', keys: { id: { type: 'string', rules: [Array] }, email: { type: 'string', flags: [Object], rules: [Array] }, password: { type: 'string', flags: [Object], rules: [Array] }, phone: { type: 'string', flags: [Object], rules: [Array] } } }
Schema description: { "type": "object", "keys": { "username": { "type": "string", "flags": { "presence": "required" }, "rules": [ { "name": "alphanum" }, { "name": "min", "args": { "limit": 3 } }, { "name": "max", "args": { "limit": 30 } } ] }, "email": { "type": "string", "flags": { "presence": "required" }, "rules": [ { "name": "email" } ] }, "birthYear": { "type": "number", "rules": [ { "name": "integer" }, { "name": "min", "args": { "limit": 1900 } }, { "name": "max", "args": { "limit": 2023 } } ] }, "password": { "type": "string", "rules": [ { "name": "pattern", "args": { "regex": "/^[a-zA-Z0-9]{3,30}$/" } } ] } } }
Express validation middleware created
This notebook has introduced Joi, a powerful schema validation library for JavaScript. We've covered:
allowUnknown
and stripUnknown
Joi is a versatile tool that can help ensure data integrity in your applications. It's particularly useful for:
For more information, check out the Joi documentation.