Skip to content

Validation

Input Validation

Jazzy includes a powerful validation engine. It allows you to define validation rules for incoming JSON data in a declarative way.

Basic Usage

The ctx.validate() helper automatically parses the request body and validates it against your rules. If validation fails, Jazzy will automatically return a 422 Unprocessable Entity response with detailed error messages.

import jazzy
proc register(ctx: Context) {.async.} =
let data = ctx.validate(%*{
"username": "required|min:3|max:20",
"email": "required|email",
"age": "int|min:18"
})
# If we reach here, validation PASSED.
# 'data' is a JsonNode containing the validated input.
let user = DB.table("users").insert(data)
ctx.json(%*{"status": "success", "id": user})

Available Validation Rules

  • required: The field must be present and not empty.
  • string, int, bool, float, json: Type checks.
  • email: Validates basic email format.
  • min:X: Minimum length (string/array) or minimum value (int/float).
  • max:X: Maximum length (string/array) or maximum value (int/float).
  • in:foo,bar,baz: The value must be one of the listed options.

Advanced Usage

Automatic 422 Handling

By default, if ctx.validate() fails, it throws a ValidationError. Jazzy catches this automatically and returns a standardized JSON response:

{
"errors": {
"username": "Field 'username' is required",
"age": "Field 'age' must be at least 18"
}
}

Manual Validation

If you want to validate a JsonNode manually without the automatic 422 response, you can catch the error:

proc manualValidation(ctx: Context) {.async.} =
try:
let data = ctx.validate(%*{"title": "required"})
except ValidationError as e:
# Custom error handling logic
ctx.status(400).json(%*{"my_custom_errors": e.errors})