NAME

Params::Validate::Strict - Validates a set of parameters against a schema

VERSION

Version 0.37

SYNOPSIS

my $schema = {
    username => { type => 'string', min => 3, max => 50 },
    age => { type => 'integer', min => 0, max => 150 },
};

my $input = {
     username => 'john_doe',
     age => '30',   # Will be coerced to integer
};

my $validated_input = validate_strict(schema => $schema, input => $input);

if(defined($validated_input)) {
    print "Example 1: Validation successful!\n";
    print 'Username: ', $validated_input->{username}, "\n";
    print 'Age: ', $validated_input->{age}, "\n";   # It's an integer now
} else {
    print "Example 1: Validation failed: $@\n";
}

Upon first reading this may seem overly complex and full of scope creep in a sledgehammer to crack a nut sort of way, however two use cases make use of the extensive logic that comes with this code and I have a couple of other reasons for writing it.

METHODS

validate_strict

Validates a set of parameters against a schema.

This function takes two mandatory arguments:

It takes optional arguments:

The schema can define the following rules for each parameter:

Example Usage

my $schema = {
  host => { type => 'string' },
  port => { type => 'integer' },
  ssl => { type => 'boolean' },
  file => { type => 'string', optional => 1 },
  content => { type => 'string', optional => 1 }
};

my $relationships = [
  {
    type => 'mutually_exclusive',
    params => ['file', 'content']
  }, {
    type => 'required_group',
    params => ['host', 'file']
  },
  {
    type => 'dependency',
    param => 'port',
    requires => 'host'
  },
  {
    type => 'value_constraint',
    if => 'ssl',
    then => 'port',
    operator => '==',
    value => 443
  }
];

my $validated = validate_strict(
  schema => $schema,
  input => $input,
  relationships => $relationships
);

MIGRATION FROM LEGACY VALIDATORS

From Params::Validate

# Old style
validate(@_, {
    name => { type => SCALAR },
    age => { type => SCALAR, regex => qr/^\d+$/ }
});

# New style
validate_strict(
    schema => {     # or "members"
        name => 'string',
        age => { type => 'integer', min => 0 }
    },
    args => { @_ }
);

From Type::Params

# Old style
my ($name, $age) = validate_positional \@_, Str, Int;

# New style - requires converting to named parameters first
my %args = (name => $_[0], age => $_[1]);
my $validated = validate_strict(
    schema => { name => 'string', age => 'integer' },
    args => \%args
);

AUTHOR

Nigel Horne, <njh at nigelhorne.com>

FORMAL SPECIFICATION

[PARAM_NAME, VALUE, TYPE_NAME, CONSTRAINT_VALUE]

ValidationRule ::= SimpleType | ComplexRule | UnionType

SimpleType ::= string | integer | number | scalar | scalarref | stringref | arrayref | hashref | coderef | object

UnionType ::= seq SimpleType    -- at least two members; written as type => ['a', 'b']

ComplexRule == [
    type: SimpleType | UnionType;
    min: ℕ₁;
    max: ℕ₁;
    optional: 𝔹;
    matches: REGEX;
    regex: REGEX;
    nomatch: REGEX;
    memberof: seq VALUE;
    enum: seq VALUE;
    values: seq VALUE;
    notmemberof: seq VALUE;
    callback: FUNCTION;
    isa: TYPE_NAME;
    can: METHOD_NAME
]

Schema == PARAM_NAME ⇸ ValidationRule

Arguments == PARAM_NAME ⇸ VALUE

ValidatedResult == PARAM_NAME ⇸ VALUE

∀ rule: ComplexRule •
  rule.min ≤ rule.max ∧
  ¬((rule.memberof ∨ rule.enum ∨ rule.values) ∧ rule.min) ∧
  ¬((rule.memberof ∨ rule.enum ∨ rule.values) ∧ rule.max) ∧
  ¬(rule.notmemberof ∧ rule.min) ∧
  ¬(rule.notmemberof ∧ rule.max)

∀ schema: Schema; args: Arguments •
  dom(validate_strict(schema, args)) ⊆ dom(schema) ∪ dom(args)

validate_strict: Schema × Arguments → ValidatedResult

∀ schema: Schema; args: Arguments •
  let result == validate_strict(schema, args) •
    (∀ name: dom(schema) ∩ dom(args) •
      name ∈ dom(result) ⇒
      type_matches(result(name), schema(name))) ∧
    (∀ name: dom(schema) •
      ¬optional(schema(name)) ⇒ name ∈ dom(args))

type_matches: VALUE × ValidationRule → 𝔹

EXAMPLE

use Params::Get;
use Params::Validate::Strict;

sub where_am_i
{
    my $params = Params::Validate::Strict::validate_strict({
        args => Params::Get::get_params(undef, \@_),
        description => 'Print a string of latitude and longitude',
        error_msg => 'Latitude is a number between +/- 90, longitude is a number between +/- 180',
        members => {
            'latitude' => {
                type => 'number',
                min => -90,
                max => 90
            }, 'longitude' => {
                type => 'number',
                min => -180,
                max => 180
            }
        }
    });

    print 'You are at ', $params->{'latitude'}, ', ', $params->{'longitude'}, "\n";
}

where_am_i({ latitude => 3.14, longitude => -155 });

BUGS

SECURITY

Taint mode

This module does not untaint its return values. When running under Perl's taint mode (-T), any value that was derived from tainted external input ($ENV{}, STDIN, etc.) will remain tainted in the validated result, even if the module accepted it. Callers that require untainted values must perform their own regex capture after validation, for example:

my $validated = validate_strict(%args);
my ($safe_name) = ($validated->{name} =~ /\A([\w\s]+)\z/);

User-supplied regex patterns

The matches rule accepts pre-compiled qr// objects supplied by the caller. A pathologically constructed pattern (e.g. qr/(a+)+b/) can cause catastrophic backtracking and peg a CPU core when matched against a hostile input value. Use possessive quantifiers (++) or atomic groups ((?>...)) in any matches pattern that will be applied to untrusted data.

Error message content

Error and warning messages produced by this module may include the parameter value supplied by the caller. The module strips ASCII control characters (including CR and LF) from all messages before passing them to the logger or croaking, to prevent log-injection and HTTP response-splitting attacks. Callers should nevertheless apply their own output encoding before including any validated value in an HTTP response, HTML page, or structured log entry.

SEE ALSO

SUPPORT

This module is provided as-is without any warranty.

Please report any bugs or feature requests to bug-params-validate-strict at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Params-Validate-Strict. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

You can find documentation for this module with the perldoc command.

perldoc Params::Validate::Strict

You can also look for information at:

LICENSE AND COPYRIGHT

Copyright 2025-2026 Nigel Horne.

This program is released under the following licence: GPL2. If you use it, please let me know.