Custom Constraints

Adding Custom Constraints

Jedison allows you to extend validation beyond standard JSON Schema rules by adding custom constraints. These are defined in the constraints option when initializing Jedison.

How Custom Constraints Work

Custom constraints are validation functions that:

  • Check for specific schema extensions (typically using x- prefixed properties)
  • Return an array of validation errors/warnings
  • Have access to the current validation context (validator, value, schema, key, path, translator)
  • Can be configured as either errors or warnings

Warning Example

A custom constraint checking x-my-constraint, reported as a warning:

constraints: {
  'x-my-constraint': (context) => {
    const errors = []
    const schemaMyConstraint = context.schema['x-my-constraint']

    if (schemaMyConstraint) {
      const invalid = context.value !== schemaMyConstraint

      if (invalid) {
        errors.push({
          type: 'warning',
          path: context.path,
          constraint: 'x-my-constraint',
          messages: [
            `Value should be equal to "${schemaMyConstraint}".`
          ]
        })
      }
    }

    return errors
  }
}

Error Example

The same shape, checking x-must-be-even, but reported as an error. Errors are what jedison.getErrors() returns by default, and are typically treated as blocking:

constraints: {
  'x-must-be-even': (context) => {
    const errors = []
    const schemaMustBeEven = context.schema['x-must-be-even']

    if (schemaMustBeEven) {
      const invalid = context.value % 2 !== 0

      if (invalid) {
        errors.push({
          type: 'error',
          path: context.path,
          constraint: 'x-must-be-even',
          messages: [
            'Value must be an even number.'
          ]
        })
      }
    }

    return errors
  }
}

Key Components

  • context object containing:
    • value - The current field value
    • path - JSON Pointer to the field
    • schema - The schema for this field
    • translator - The Translator instance
  • Error objects with:
    • type - 'error' or 'warning' severity level
    • path - Location of the validation issue
    • constraint - Name of the constraint
    • messages - User-friendly error messages

Error Handling and Validation States

Jedison provides flexible error handling through the getErrors() method:

  • jedison.getErrors() - Returns only error-level validations (default)
  • jedison.getErrors(['error', 'warning']) - Returns both errors and warnings

Benefits of Warning-Level Constraints

Using warning-level constraints provides several advantages:

  • Soft validation - Users can proceed with warnings while being informed of potential issues
  • Progressive validation - Start with warnings that can be upgraded to errors later
  • Better UX - Different visual treatment for errors (blocking) vs warnings (advisory)
  • Flexible workflows - Allow submission with warnings while maintaining data quality standards

In the examples above, warnings and errors display independently — warnings (yellow) and errors (red). By default, getErrors() only returns errors, while warnings are still shown in the UI. To include warnings in the validation result, pass an array of filters: ['error', 'warning']. Final validation behavior is left to the user's implementation.