Normandy.Schema.Validator (normandy v2.2.0)

View Source

Runtime validation of data against Normandy schemas.

This module provides functions to validate arbitrary data against Normandy schema specifications, ensuring data conforms to the defined JSON Schema constraints.

Examples

defmodule UserSchema do
  use Normandy.Schema

  schema do
    field :name, :string, required: true, min_length: 1
    field :age, :integer, minimum: 0, maximum: 150
    field :email, :string, format: "email"
  end
end

# Valid data
{:ok, _} = Normandy.Schema.Validator.validate(
  UserSchema,
  %{name: "Alice", age: 30, email: "alice@example.com"}
)

# Invalid data
{:error, errors} = Normandy.Schema.Validator.validate(
  UserSchema,
  %{age: -5}
)

Validation Features

This validator supports the following JSON Schema validations:

  • Type validation - Ensures values match their declared types (:date, :time and :duration fields are JSON strings with a format; the matching Date, Time or Duration value is accepted too)
  • Required fields - Validates required fields are present
  • String constraints
    • minLength / min_length - Minimum string length
    • maxLength / max_length - Maximum string length
    • pattern - Regular expression pattern matching
    • format - String format validation (email, uri, uuid, date-time, date, time, duration, hostname, ipv4, ipv6)
  • Number constraints
    • minimum - Minimum value (inclusive)
    • maximum - Maximum value (inclusive)
    • exclusiveMinimum - Minimum value (exclusive)
    • exclusiveMaximum - Maximum value (exclusive)
    • multipleOf / multiple_of - Value must be a multiple of the number
  • Array constraints
    • minItems / min_items - Minimum array length
    • maxItems / max_items - Maximum array length
    • uniqueItems / unique_items - Ensures array items are unique
  • Object constraints
    • additionalProperties - false rejects keys outside properties; a schema checks their values (a {:map, inner} field emits this)
    • patternProperties - Checks the values of keys matching a regex
  • Enum validation - Ensures values are in allowed list
  • const - Value must equal the given value
  • Composition - anyOf, oneOf, allOf for complex type unions and intersections
  • not - Value must not match the schema
  • Conditionals - if/then/else schemas for context-dependent validation
  • Nested schemas - Validates nested objects and arrays recursively

Every keyword applies at every level: the root, each field, array items, and each composition or conditional sub-schema.

Format Validation

The validator supports the following ten string formats (any other format is not checked):

  • email - RFC 5322 email addresses (simplified)
  • uri - Uniform Resource Identifiers
  • uuid - UUID (Universally Unique Identifier) format
  • date-time - ISO 8601 date-time format
  • date - ISO 8601 calendar date
  • time - ISO 8601 time of day
  • duration - ISO 8601 duration (P1Y2M3W4DT5H6M7.5S; at least one part)
  • hostname - RFC 1123 hostname
  • ipv4 - IPv4 address format
  • ipv6 - IPv6 address format (simplified)

Error Format

Validation errors are returned as a list of maps with the following structure:

%{
  path: [:field, :nested_field],  # Path to the invalid field
  message: "error message",        # Human-readable error message
  constraint: :minimum             # The constraint that failed
}

Summary

Functions

Validates data against a Normandy schema module.

Validates data against a Normandy schema module, raising on error.

Functions

validate(schema_module, data)

Validates data against a Normandy schema module.

Returns {:ok, data} if validation succeeds, or {:error, errors} if validation fails.

Examples

validate(MySchema, %{name: "Alice"})
#=> {:ok, %{name: "Alice"}}

validate(MySchema, %{age: -1})
#=> {:error, [%{path: [:age], message: "must be >= 0", constraint: :minimum}]}

validate!(schema_module, data)

Validates data against a Normandy schema module, raising on error.

Returns the data if validation succeeds, or raises a Normandy.Schema.ValidationError if validation fails.

Examples

validate!(MySchema, %{name: "Alice"})
#=> %{name: "Alice"}

validate!(MySchema, %{age: -1})
#=> ** (Normandy.Schema.ValidationError) Validation failed: age must be >= 0