Logo
⚠️ Unsaved
[M]:

Joi Complete Guide: Building and Validating Schemas

This notebook provides a comprehensive guide to Joi, the powerful schema description language and data validator for JavaScript. We'll explore advanced schema building techniques, validation strategies, and real-world examples to help you implement robust data validation in your Node.js applications.

[52]:
$ npm install joi

up to date in 425ms

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

1. Schema Building Fundamentals

Let's start by understanding the core components of Joi schemas and how to build them effectively.

[54]:
Basic schema types:
String schema: { type: 'string' } 
Number schema: { type: 'number' } 
Boolean schema: { type: 'boolean' } 
[55]:
Complex user schema structure:
{
  "type": "object",
  "keys": {
    "id": {
      "type": "string",
      "rules": [
        {
          "name": "guid",
          "args": {
            "options": {
              "version": "uuidv4"
            }
          }
        }
      ]
    },
    "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",
          "args": {
            "options": {
              "tlds": {
                "allow": false
              }
            }
          }
        }
      ]
    },
    "password": {
      "type": "string",
      "flags": {
        "presence": "required"
      },
      "rules": [
        {
          "name": "pattern",
          "args": {
            "regex": "/^[a-zA-Z0-9]{8,30}$/"
          }
        }
      ]
    },
    "birthYear": {
      "type": "number",
      "rules": [
        {
          "name": "integer"
        },
        {
          "name": "min",
          "args": {
            "limit": 1900
          }
        },
        {
          "name": "max",
          "args": {
            "limit": 2025
          }
        }
      ]
    },
    "createdAt": {
      "type": "date",
      "flags": {}
    },
    "roles": {
      "type": "array",
      "flags": {
        "default": [
          "user"
        ]
      },
      "items": [
        {
          "type": "string",
          "flags": {
            "only": true
          },
          "allow": [
            "user",
            "admin",
            "editor"
          ]
        }
      ]
    }
  }
} 
[M]:

2. Schema Composition and Reuse

Learn how to compose and reuse schemas for better maintainability.

[56]:
[57]:
Login validation result:
{
  value: {
    email: 'user@example.com',
    password: 'Password123',
    rememberMe: false
  }
} 
[58]:
Registration validation result:
{
  value: {
    username: 'johndoe',
    email: 'john@example.com',
    password: 'Password123',
    confirmPassword: 'Password123',
    createdAt: 1741806806068
  }
} 
Created timestamp type: number 
[M]:

3. Advanced String Validation

Explore advanced string validation techniques for common use cases.

[59]:
[60]:
URL validation:
Valid URL: { value: 'https://example.com' } 
Invalid URL: {
  value: 'ftp://example.com',
  error: [Error [ValidationError]: "value" must be a valid uri with a scheme matching the http|https pattern] {
    _original: 'ftp://example.com',
    details: [ [Object] ]
  }
} 
[61]:
Credit card validation:
Valid card: { value: '4111111111111111' } 
Invalid card: {
  value: '1234567812345678',
  error: [Error [ValidationError]: "value" must be a credit card] {
    _original: '1234567812345678',
    details: [ [Object] ]
  }
} 
[M]:

4. Number and Date Validation

Explore advanced number and date validation techniques.

[62]:
[63]:
Number validation examples:
Integer validation: { value: 42 } 
Integer validation (invalid): {
  value: 42.5,
  error: [Error [ValidationError]: "value" must be an integer] {
    _original: 42.5,
    details: [ [Object] ]
  }
} 
Precision validation: { value: 99.99 } 
Multiple of 5 validation: { value: 25 } 
Multiple of 5 validation (invalid): {
  value: 27,
  error: [Error [ValidationError]: "value" must be a multiple of 5] {
    _original: 27,
    details: [ [Object] ]
  }
} 
[64]:
[65]:
Date validation examples:
Past date validation: { value: 2020-01-01T00:00:00.000Z } 
Future date validation: { value: 2026-03-12T19:13:32.678Z } 
ISO date validation: { value: 2023-05-15T14:30:00.000Z } 
[M]:

5. Object Schema Advanced Techniques

Explore advanced techniques for object schema validation.

[66]:
Metadata validation with pattern keys:
{
  value: {
    id: '123',
    name: 'Test Item',
    meta_color: 'blue',
    meta_size: 'large',
    meta_material: 'cotton'
  }
} 
[67]:
Strict schema validation (unknown keys rejected):
{
  value: { name: 'John', age: 30, country: 'USA' },
  error: [Error [ValidationError]: "country" is not allowed] {
    _original: { name: 'John', age: 30, country: 'USA' },
    details: [ [Object] ]
  }
} 
[68]:
Flexible schema validation (unknown keys allowed):
{ value: { name: 'John', age: 30, country: 'USA' } } 
[69]:
[70]:
Credit card payment validation:
{
  value: {
    paymentMethod: 'credit_card',
    cardNumber: '4111111111111111',
    expiryDate: '12/25'
  }
} 
[71]:
PayPal payment validation (with forbidden field):
{
  value: {
    paymentMethod: 'paypal',
    paypalEmail: 'user@example.com',
    cardNumber: '4111111111111111'
  },
  error: [Error [ValidationError]: "cardNumber" is not allowed] {
    _original: {
      paymentMethod: 'paypal',
      paypalEmail: 'user@example.com',
      cardNumber: '4111111111111111'
    },
    details: [ [Object] ]
  }
} 
[M]:

6. Array Schema Advanced Techniques

Explore advanced techniques for array schema validation.

[72]:
Basic array validation:
Valid tags: { value: [ 'javascript', 'nodejs', 'validation' ] } 
Invalid tags (too many): {
  value: [ 'a', 'b', 'c', 'd', 'e', 'f' ],
  error: [Error [ValidationError]: "value" must contain less than or equal to 5 items] {
    _original: [ 'a', 'b', 'c', 'd', 'e', 'f' ],
    details: [ [Object] ]
  }
} 
[73]:
Ordered array validation:
Valid 2D coordinates: { value: [ 10, 20 ] } 
Valid 3D coordinates: { value: [ 10, 20, 30 ] } 
Invalid coordinates (missing y): {
  value: [ 10 ],
  error: [Error [ValidationError]: "value" does not contain 1 required value(s)] {
    _original: [ 10 ],
    details: [ [Object] ]
  }
} 
[74]:
Mixed array validation:
Valid mixed array: { value: [ 'hello', 42, true, 'world' ] } 
Invalid mixed array: {
  value: [ 'hello', 42, true, { key: 'value' } ],
  error: [Error [ValidationError]: "[3]" does not match any of the allowed types] {
    _original: [ 'hello', 42, true, [Object] ],
    details: [ [Object] ]
  }
} 
[75]:
Unique array validation:
Valid unique array: { value: [ 'a', 'b', 'c' ] } 
Invalid unique array: {
  value: [ 'a', 'b', 'a' ],
  error: [Error [ValidationError]: "[2]" contains a duplicate value] {
    _original: [ 'a', 'b', 'a' ],
    details: [ [Object] ]
  }
} 
[76]:
Complex array validation:
Valid users array: {
  value: [
    { id: 1, name: 'John', email: 'john@example.com' },
    { id: 2, name: 'Jane', email: 'jane@example.com' }
  ]
} 
[M]:

7. Conditional Validation

Explore advanced conditional validation techniques.

[77]:
Basic conditional validation:
Valid admin user: {
  value: { role: 'admin', permissions: [ 'read', 'write', 'delete' ] }
} 
Invalid admin user (missing permissions): {
  value: { role: 'admin' },
  error: [Error [ValidationError]: "permissions" is required] {
    _original: { role: 'admin' },
    details: [ [Object] ]
  }
} 
Valid regular user (no permissions needed): { value: { role: 'user' } } 
[78]:
[79]:
Standard shipping validation:
{
  value: {
    shippingMethod: 'standard',
    domesticAddress: {
      street: '123 Main St',
      city: 'Anytown',
      state: 'CA',
      zipCode: '12345'
    }
  }
} 
[80]:
Express shipping validation:
{
  value: {
    shippingMethod: 'express',
    domesticAddress: {
      street: '123 Main St',
      city: 'Anytown',
      state: 'CA',
      zipCode: '12345'
    },
    phoneNumber: '1234567890'
  }
} 
[81]:
International shipping validation:
{
  value: {
    shippingMethod: 'international',
    internationalAddress: {
      street: '123 Global Ave',
      city: 'London',
      postalCode: 'SW1A 1AA',
      country: 'United Kingdom'
    }
  }
} 
[82]:
Invalid shipping validation:
{
  value: {
    shippingMethod: 'international',
    domesticAddress: {
      street: '123 Main St',
      city: 'Anytown',
      state: 'CA',
      zipCode: '12345'
    }
  },
  error: [Error [ValidationError]: "domesticAddress" is not allowed] {
    _original: { shippingMethod: 'international', domesticAddress: [Object] },
    details: [ [Object] ]
  }
} 
[M]:

8. Custom Validation Functions

Create custom validation logic for complex requirements.

[83]:
[84]:
[85]:
[86]:
Valid product validation:
{
  value: {
    name: 'Wireless Headphones',
    price: 99.99,
    salePrice: 79.99,
    quantity: 50,
    category: 'Electronics',
    tags: [ 'wireless', 'audio', 'bluetooth' ]
  }
} 
[87]:
Invalid product validation (sale price too high):
{
  value: {
    name: 'Wireless Headphones',
    price: 99.99,
    salePrice: 109.99,
    quantity: 50,
    category: 'Electronics',
    tags: [ 'wireless', 'audio', 'bluetooth' ]
  },
  error: [Error [ValidationError]: Error code "product.invalidSalePrice" is not defined, your custom type is missing the correct messages definition] {
    _original: {
      name: 'Wireless Headphones',
      price: 99.99,
      salePrice: 109.99,
      quantity: 50,
      category: 'Electronics',
      tags: [Array]
    },
    details: [ [Object] ]
  }
} 
[M]:

9. Schema Transformation and Defaults

Learn how to transform data and set default values during validation.

[88]:
[89]:
[90]:
Blog post with transformations and defaults:
{
  value: {
    title: 'Introduction to Joi Schema Validation',
    content: 'This is a comprehensive guide to using Joi for schema validation in your Node.js applications. We will cover basic and advanced validation techniques.This is a comprehensive guide to using Joi for schema validation in your Node.js applications. We will cover basic and advanced validation techniques.This is a comprehensive guide to using Joi for schema validation in your Node.js applications. We will cover basic and advanced validation techniques.',
    author: 'John Doe',
    tags: [],
    status: 'draft',
    createdAt: 1741806838238,
    views: 0,
    featured: false,
    slug: 'introduction-to-joi-schema-validation',
    excerpt: 'This is a comprehensive guide to using Joi for schema validation in your Node.js applications. We will cover basic and advanced validation techniques....'
  }
} 
[M]:

10. Schema Extensions and Plugins

Learn how to extend Joi with custom types and validation rules.

[91]:
[92]:
[93]:
Book validation with ISBN-10:
{
  value: {
    title: 'JavaScript: The Good Parts',
    author: 'Douglas Crockford',
    isbn10: '0596517742',
    publisher: "O'Reilly Media",
    publicationYear: 2008
  }
} 
[94]:
Book validation with ISBN-13:
{
  value: {
    title: 'Eloquent JavaScript',
    author: 'Marijn Haverbeke',
    isbn13: '9781593279509',
    publisher: 'No Starch Press',
    publicationYear: 2018
  }
} 
[95]:
Book validation without ISBN:
{
  value: {
    title: 'Some Book',
    author: 'Some Author',
    publisher: 'Some Publisher',
    publicationYear: 2020
  },
  error: [Error [ValidationError]: "value" must contain at least one of [isbn10, isbn13]] {
    _original: {
      title: 'Some Book',
      author: 'Some Author',
      publisher: 'Some Publisher',
      publicationYear: 2020
    },
    details: [ [Object] ]
  }
} 
[96]:
Book validation with invalid ISBN:
{
  value: {
    title: 'Invalid ISBN Book',
    author: 'Test Author',
    isbn10: '123456789',
    publisher: 'Test Publisher',
    publicationYear: 2021
  },
  error: [Error [ValidationError]: "isbn10" must be a valid ISBN-10] {
    _original: {
      title: 'Invalid ISBN Book',
      author: 'Test Author',
      isbn10: '123456789',
      publisher: 'Test Publisher',
      publicationYear: 2021
    },
    details: [ [Object] ]
  }
} 
[M]:

Summary

This notebook has provided a comprehensive guide to building and validating schemas with Joi. We've covered:

  1. Schema Building Fundamentals: Core components and structure of Joi schemas
  2. Schema Composition and Reuse: Creating modular, reusable schema components
  3. Advanced String Validation: Complex string validation for URLs, emails, and patterns
  4. Object Schema Techniques: Nested objects, unknown keys, and schema references
  5. Alternatives and Conditional Logic: Using alternatives and conditional validation
  6. Array Schema Advanced Techniques: Validating arrays with various constraints
  7. Conditional Validation: Creating schemas with complex conditional logic
  8. Custom Validation Functions: Implementing custom validation rules
  9. Schema Transformation and Defaults: Transforming data and setting defaults
  10. Schema Extensions and Plugins: Extending Joi with custom types and rules

Joi provides a powerful, flexible system for data validation in JavaScript applications. By leveraging these techniques, you can ensure data integrity, improve error handling, and create more robust applications.

For more information, check out the Joi documentation.

Sign in to save your work and access it from anywhere