NAME

Validate::Simple - (Relatively) Simple way to validate input parameters

SYNOPSIS

use Validate::Simple;

my $specs = {
    username => {
        type     => 'string',
        required => 1,
    },
    first_name => {
        type     => 'string',
        required => 1,
    },
    last_name => {
        type => 'string',
    },
    age => {
        type => 'integer',
        gt   => 18,
    },
    gender => {
        type   => 'enum',
        values => [
            'mail',
            'femaile',
            'id_rather_not_to_say',
        ],
    },
    tags => {
        type => 'array',
        of   => {
            type => 'string',
        },
    },
    hobbies => {
        type => 'array',
        of   => {
            type =>'enum',
            values => [ qw/hiking travelling surfing laziness/ ],
        }
    },
    score => {
        type => 'hash',
        of   => 'non_negative_int',
    },
    monthly_score => {
        type => 'hash',
        of   => {
            type => 'hash',
            of   => {
                type     => 'arrray',
                callback => sub {
                    @{ $_[0] } < 12;
                },
            }
        },
    }
};

my $vs1 = Validate::Simple->new( $specs );
my $is_valid1 = $vs1->validate( $params );
print join "\n", $$vs1->errors()
    if !$is_valid1;

# Or

my $vs2 = Validate::Simple->new();
my $is_valid2 = $vs2->validate( $params, $specs );
print join "\n", $vs2->errors()
    if !$is_valid2;

DESCRIPTION

The module validates parameters against specifications. It was designed to validate form parameters or JSON-like structures.

LOGIC

The main use case is the following: an application receives a from parameters, or a JSON-object, you transform it into a Perl structure, create a specification of an expected data and validate against this specification. A specification is just a hashref with the keys same as parameters names and values are hashrefs with rules for a specific parameter.

For example:

my $spec = {
    username => {
        type       => 'string',
        required   => 1,
        min_length => 1,
        max_length => 255,
    },
    password => {
        type       => 'string',
        required   => 1,
        min_length => 12,
    },
    subscriptions => {
        type => 'array',
        of   => {
            type => 'positive_int',
        },
    }
};

This specification may be used to validate a sign up form, on which a user is expected to enter a non-empty username with length no longer than 255 character, a password no shorter than 12 characters and to choose a subscriptions, which are passed as a list of IDs, i.e. positive integers. The subscriptions may not be passed at all.

EXPORT

This module does not export anything. It is supposed to be used to to create a validation objects, which can be reused as many times as necessry.

SPECIFICATIONS (SPECS)

Specifications are the rules that describe what parameter are expected, their types and constraints (like lengths of strings or signs of numbers) Specification is just a hashref, the keys are parameters names, and values are descriptions of expected values.

Every description must have a type key, and may have the keys required, undef and callback.

Common specs keys

type

The value of type defines an expected type of a parameter. You can more about supported types in the "Types" section.

required

If set to a true value, the parameter is required, and if it is not in the form data, the form is considered invalid. If it set to a false value or does not exists, the parameter is optional.

undef

By default neither parameter can be undefined. If you expect some values to be undefined, you need explicitly set to this key to true.

For example, if you allow the value of the param to be literally anything, you may do the following:

my $spec = {
    whatever => {
        type  => 'any',
        undef => 1,
    }
};

callback

If you have some special constraints to a value that does not fit to any of supported types, you may specify your own function to validate the value. The callback key expects a coderef as a value. The function should receive the value as a first parameter.

For example, if you need to check whether a value is an even positive integer, you can do the following:

my $spec = {
    even_positive => {
        type     => "positive_int",
        callback => sub { !( $_[0] % 2 ) },
    },
};

In case of the "enum" type, the second parameter is the hashref with the keys of allowed enum values.

The callback function is called after checking type and constraints.

Types

any

The value can be of any type (including array or hash), except undef.

Number types

All number types supposrt the following keys:

gt

Greater than.

ge

Greater than or equal to.

lt

Less than.

le

Less than or equal to.

For example, the follwong spec checks whether it's a valid month number:

my $spec = {
    month => {
        type => 'positive_int',
        le   => 12,
    },
};

number

The value is a valid number. On the bacstage it simply performs looks_like_number from Scalar::Util.

positive

Same as "number", and checks whether it greater than 0.

non_negative

Same as "number", and checks whether it greater than or equal to 0.

negative

Same as "number", and checks whether it greater than 0.

non_positive

Same as "number", and checks whether it less than or equal to 0.

integer

The value is an integer. It performs is_int from Data::Types.

positive_int

The value is a positive integer. It performs is_count from Data::Types.

non_negative_int

The value is a non-negative positive integer. It performs is_whole from Data::Types.

negative_int

The value is a negative integer.

non_positive_int

The value is a non-positive integer.

string

The value is a string. It performs is_string from Data::Types.

NOTE: Any number is a valid string, so both $params1 = { string_param => 5 }; and $params1 = { string_param => "5" }; will pass.

You can add constraints to the string length, by adding keys max_length and min_length. Either key must be a positive integer.

List types

The list types must have the key of, which contain a spec of all list values. For example:

my $spec = {
    ids => {
        type => 'array',
        of   => {
            type => 'positive_int',
        },
    },
    placeholders => {
        type => 'hash',
        of   => {
            type => 'string',
        },
    },
};

As long as the of key expects another specification, you can easily validate a complex structures, like array of arrays of strings, hash of arrays of hashes of enums, arrays of hashes of arrays of arrays of any, and so on.

By default lists cannot be empty. If you expect an empty list, you should add a key empty and set it to a true value.

array

The value is an arrayref.

hash

The value is a hashref;

enum

The value is one of the predefined list.

Enum type always contains a string. The list of predefined strings is provided in the values key, which is required for enums:

my $spec = {
    data_types => {
        type   => 'enum',
        values => [
            qw/
                  any
                  number
                  positive
                  non_negative
                  negative
                  non_positive
                  integer
                  positive_int
                  non_negative_int
                  negative_int
                  non_positive_int
                  string
                  array
                  hash
                  enum
                  code
            /
        ],
    }
};

code

The value is a coderef. Validate::Simple only checks the type, it does not run the code and does not check it's result.

METHODS

new( \%spec )

Creates an object. The parameter is optional, though it's recomended to pass it, because in this case it checks scpecs syntax only once, not on each call of validate method.

validate( \%params, \%specs )

Does validation of the \%params against \%specs. If \%specs is not provided, performs validation against the spec, given in the new method.

errors

Returns the list of validation errors.

BUGS

Not reported... Yet...

SEE ALSO

AUTHOR

Andrei Pratasavitski <andrei.protasovitski@gmail.com>

LICENSE

This is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.