Logo
⚠️ Unsaved
[M]:

Joi 101: Getting Started with Schema Validation

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.

[1]:
$ npm install joi

added 6 packages in 7s

28 packages are looking for funding
  run `npm fund` for details
[2]:
Joi version: 17.13.3 
[M]:

1. Basic Validation

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.

[3]:
[4]:
Valid user validation result:
{
  value: {
    username: 'johndoe',
    email: 'john@example.com',
    birthYear: 1990,
    password: 'password123'
  }
} 
[5]:
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] ]
  }
} 
[M]:

2. Validation Options

Joi provides several options to customize the validation behavior.

[6]:
[7]:
[8]:
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] ]
  }
} 
[9]:
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'
    }
  }
} 
[10]:
Validation with stripUnknown: true:
{
  value: {
    name: 'Jane Smith',
    age: 28,
    email: 'jane@example.com',
    address: { street: '123 Main St', city: 'Anytown', zipCode: '12345' }
  }
} 
[11]:
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] ]
  }
} 
[M]:

3. Advanced Validation Rules

Joi provides a rich set of validation rules for different data types.

[12]:
[13]:
[52]:
Error during execution: Unknown date format yyyy
[15]:
[16]:
[17]:
[M]:

4. Conditional Validation

Joi allows you to create schemas with conditional validation logic.

[18]:
[19]:
Personal account validation result:
{
  value: {
    username: 'johndoe',
    password: 'password123',
    accountType: 'personal'
  }
} 
[20]:
Business account validation result:
{
  value: {
    username: 'acmecorp',
    password: 'securepass123',
    accountType: 'business',
    companyName: 'ACME Corporation',
    taxId: '123-45-6789'
  }
} 
[21]:
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] ]
  }
} 
[M]:

5. Custom Validation Messages

Joi allows you to customize error messages for better user experience.

[22]:
[23]:
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] ]
  }
} 
[24]:
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'
} 
[M]:

6. API Request Validation

Let's see how Joi can be used to validate API requests in a real-world scenario.

[25]:
[26]:
[27]:
[28]:
[29]:
[30]:
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'
  }
} 
[31]:
[32]:
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' }
  }
] 
[M]:

7. Environment Configuration Validation

Joi is great for validating environment variables and configuration objects.

[33]:
[34]:
[35]:
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 
[M]:

8. Custom Validation Functions

Joi allows you to create custom validation functions for complex validation logic.

[36]:
[37]:
[38]:
[39]:
Valid order validation result:
{
  value: {
    customerId: 'cust123',
    items: [ [Object], [Object] ],
    total: 46.97
  }
} 
[40]:
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] ]
  }
} 
[M]:

9. Performance Considerations

Let's look at some performance considerations when using Joi.

[41]:
[42]:
[43]:
[44]:
[45]:
Error during execution: console.time is not a functionPerformance test:
[46]:
Error during execution: console.time is not a function
[47]:
Error during execution: console.time is not a function
[M]:

10. Practical Tips for Using Joi

Here are some practical tips for using Joi effectively in your projects.

[48]:
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] }
  }
} 
[49]:
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}$/"
          }
        }
      ]
    }
  }
} 
[50]:
Express validation middleware created
[M]:

Summary

This notebook has introduced Joi, a powerful schema validation library for JavaScript. We've covered:

  1. Basic Validation: Creating schemas and validating data against them
  2. Validation Options: Customizing validation behavior with options like allowUnknown and stripUnknown
  3. Advanced Validation Rules: Using Joi's rich set of validation rules for different data types
  4. Conditional Validation: Creating schemas with conditional validation logic
  5. Complex Object Validation: Validating nested objects and arrays
  6. API Request Validation: Using Joi to validate API requests
  7. Environment Configuration Validation: Validating environment variables and configuration objects
  8. Custom Validation Functions: Creating custom validation logic
  9. Performance Considerations: Understanding performance implications
  10. Practical Tips: Best practices for using Joi effectively

Joi is a versatile tool that can help ensure data integrity in your applications. It's particularly useful for:

  • Validating user input in forms
  • Validating API requests and responses
  • Validating configuration objects
  • Ensuring data consistency in your application

For more information, check out the Joi documentation.

Sign in to save your work and access it from anywhere