NAME
Params::Sah - Validate method/function parameters using Sah schemas
VERSION
This document describes version 0.073 of Params::Sah (from Perl distribution Params-Sah), released on 2021-08-04.
SYNOPSIS
use Params::Sah qw(gen_validator);# for subroutines that accept positional parameters. all parameters required,# but you can pass undef to the third param.sub mysub1 { state $validator = gen_validator('str*', ['array*', min_len=>1], 'int'); $validator->(\@_); ...}mysub1("john", ['a']); # dies, the third argument is not passedmysub1("john", ['a'], 2); # okmysub1("john", ['a'], 2, 3); # dies, extra parametermysub1("john", ['a'], undef); # ok, even though the third argument is undefmysub1([], ['a'], undef); # dies, first argument does not validatemysub1("john", [], undef); # dies, second argument does not validate# for subroutines that accept positional parameters (this time arrayref instead# of array), some parameters optional. also this time we use 'allow_extra'# option to allow additional positional parameters.sub mysub1b { my $args = shift; state $validator = gen_validator({optional_params=>[2], allow_extra=>1}, 'str*', 'array*', 'int'); $validator->($args); ...}mysub1b(["john", ['a']]); # ok, the third argument is optionalmysub1b(["john", ['a'], 2]); # okmysub1b(["john", ['a'], undef]); # okmysub1b(["john", ['a'], 2, 3]); # ok, extra params allowed# for subroutines that accept named parameters (as hash). all parameters# required, but you can pass undef to the 'age' parameter.sub mysub2 { my %args = @_; state $validator = gen_validator({named=>1}, name=>'str*', tags=>['array*', min_len=>1], age=>'int'); $validator->(\%args); ...}mysub2(name=>"john", tags=>['a']); # dies, the 'age' argument is not passedmysub2(name=>"john", tags=>['a'], age=>32); # okmysub2(name=>"john", tags=>['a'], age=>undef); # ok, even though the 'age' argument is undefmysub2(name=>[], tags=>['a'], age=>undef); # dies, the 'name' argument does not validatemysub2(name=>"john", tags=>[], age=>undef); # dies, the 'tags' argument does not validate# for subroutines that accept named parameters (this time as hashref). some# parameters optional. also this time we want to allow extra named parameters.sub mysub2b { my $args = shift; state $validator = gen_validator( {named=>1, optional_params=>['age'], allow_extra=>1}, name=>'str*', tags=>['array*', min_len=>1], age=>'int*', ); $validator->($args); ...}mysub2b({name=>"john", tags=>['a']}); # okmysub2b({name=>"john", tags=>['a'], age=>32}); # okmysub2b({name=>"john", tags=>['a'], age=>32, foo=>1}); # ok, extra param 'foo' allowedmysub2b({name=>"john", tags=>['a'], age=>undef}); # dies, this time, 'age' cannot be undef
Example with more complex schemas, with default value and coercion rules:
sub mysub2c { my %args = @_; state $validator = gen_validator( {named => 1, optional_params => ['age']}, name => ['str*', min_len=>4, match=>qr/\S/, default=>'noname'], age => ['int', min=>17, max=>120], tags => ['array*', min_len=>1, of=>['str*', match=>qr/\A\w+\z/], 'x.perl.coerce_rules'=>['From_str::comma_sep']], ); $validator->(\%args); ...}mysub2c(tags=>['a']); # after validation, %args will be: (name=>'noname', tags=>['a'])mysub2c(name=>"mark", tags=>['b,c,d']); # after validation, %args will be: (name=>'mark', tags=>['b','c','d'])
Validator generation options:
# default is to 'croak', valid values include: carp, die, warn, bool, strgen_validator({on_invalid=>'croak'}, ...);
DESCRIPTION
This module provides a way for functions to validate their parameters usingSah schemas.
VARIABLES
$DEBUG
Bool. If set to true will print validator code when generated.
$OPT_BACKEND
Str. Used to set default forbackend
option.
$OPT_ALLOW_EXTRA
Bool. Used to set default forallow_extra
option.
$OPT_ON_INVALID
String. Used to set default foron_invalid
option.
$OPT_ERR_DETAIL
Bool. Used to set default forerr_detail
option.
$OPT_DISABLE
Bool. Used to set default fordisable
option.
$OPT_NAMED
Bool. Used to set default fornamed
option.
PERFORMANCE NOTES
See benchmarks inBencher::Scenarios::ParamsSah.
FUNCTIONS
None exported by default, but exportable.
gen_validator([\%opts, ] ...) => code
Generate code for subroutine validation. It accepts an optional hashref as the first argument for options. The rest of the arguments are Sah schemas that correspond to the function parameters in the same position, i.e. the first schema will validate the function's first argument, and so on. Example:
gen_validator('schema1', 'schema2', ...);gen_validator({option=>'val', ...}, 'schema1', 'schema2', ...);
Will return a coderef which is the validator code. The validator code accepts an arrayref (usually\@_
). The validator code will by default croak on invalid parameters, but this behavior can be customized using theon_invalid
option.
Known options:
backend => str (default: Data::Sah)
Can be set to the experimentalData::Sah::Tiny to speed up validator generation for simpler schemas.
named => bool (default: 0)
If set to true, it means we are generating validator for subroutine that accepts named parameters (e.g.
f(name=>'val', other=>'val2')
) instead of positional (e.g.f('val', 'val2')
). The validator will accept the parameters as a hashref. And the arguments ofgen_validator
are assumed to be a hash of parameter names and schemas instead of a list of schemas, for example:gen_validator({named=>1}, arg1=>'schema1', arg2=>'schema2', ...);
optional_params => array
By default all parameters are required. This option specifies which parameters should be made optional. For positional parameters, specify the index (0-based).
allow_extra => bool (default: 0)
If set to one then additional positional or named parameters are allowed (and not validated). By default, no extra parameters are allowed.
on_invalid => str (default: 'croak')
What should the validator code do when function parameters are invalid? The default is to croak (seeCarp) to report error to STDERR from the caller perspective. Other valid choices include:
warn
,carp
,die
,bool
(return false on invalid, or true on valid),str
(return an error message on invalid, or empty string on valid).invalid_detail => bool (default: 0)
If set to true, will generate a more detailed error message. For example, with this schema:
[str => {min_len=>4}]
then the string
'foo'
will fail to validate with this error message "Length must be at least 4". Otherwise, the error message will just be something like: "Fail schema ['str', {min_len=>1}]". By default this option is set to false for slightly faster validation.disable => bool (default: 0)
If set to 1, will return an empty coderef validator. Used to disable parameter checking. Usually via setting"$OPT_DISABLE" to disable globally.
FAQ
How do I learn more about Sah (the schema language)?
See the specification:Sah. TheSah::Examples distribution also contains more examples. Also, for other examples, lots of my distributions containRinci metadata which includes schemas for each function arguments.
Why does the validator code accept arrayref/hashref instead of array/hash?
To be able to modify the original array/hash, e.g. set default value.
What if my subroutine accepts a mix of positional and named parameters?
You can put all your parameters in a hash first, then feed it to the validator. For example:
sub mysub { my %args; %args = %{shift} if req $_[0] eq 'HASH'; # accept optional hashref ($args{x}, $args{y}) = @_; # positional params state $validator = gen_validator( {named=>1, optional_params=>['opt1','opt2']}, x=>"posint*", y=>"negint*", opt1=>"str*", opt2=>"str", ); $validator->(\%args); ...}mysub(1, -2); # ok, after validation %args will become (x=>1, y=>-2)mysub({}, 1, -2); # ok, after validation %args will become (x=>1, y=>-2)mysub({opt1=>"foo"}, 1, -2); # ok, after validation %args will become (x=>1, y=>-2, opt1=>"foo")mysub({opt3=>"foo"}, 1, -2); # dies, unknown option 'opt3'mysub({opt1=>"foo"}, 1); # dies, missing required arg 'x'mysub({opt1=>[]}, 1, -2); # dies, 'opt1' argument doesn't validate
How to give default value to parameters?
By using the Sahdefault
clause in your schema:
gen_validator(['str*', default=>'green']);
How to make some parameters optional?
By using theoptional_params
option, which is an array of parameter names to make optional. To set a positional parameter optional, specify its index (0-based) as name.
Why is my program failing with error message: Can't call method "state" on an undefined value?
You need to specify that you want to usestate
variables, either by:
# at leastuse 5.010;
or:
use feature 'state';
How do I see the validator code being generated?
Set$Params::Sah::DEBUG=1
beforegen_validator()
, for example:
use Params::Sah qw(gen_validator);$Params::Sah::DEBUG = 1;gen_validator('int*', 'str');
Sample output:
1|sub(\@) { 2| my $_ps_args = shift; 3| my $_ps_res; | | 6| ### validating 0: 7| no warnings 'void'; 8| my $_sahv_dpath = []; 9| Carp::croak("arg0: $_ps_res") if !( # req #010| ((defined($_ps_args->[0])) ? 1 : (($_ps_res //= (@$_sahv_dpath ? '@'.join("/",@$_sahv_dpath).": " : "") . "Required but not specified"),0)) |12| && |14| # check type 'int'15| ((Scalar::Util::Numeric::isint($_ps_args->[0])) ? 1 : (($_ps_res //= (@$_sahv_dpath ? '@'.join("/",@$_sahv_dpath).": " : "") . "Not of type integer"),0))); | |18| ### validating 1:19| Carp::croak("arg1: $_ps_res") if !( # skip if undef20| (!defined($_ps_args->[1]) ? 1 : |22| (# check type 'str'23| ((!ref($_ps_args->[1])) ? 1 : (($_ps_res //= (@$_sahv_dpath ? '@'.join("/",@$_sahv_dpath).": " : "") . "Not of type text"),0)))));24| return; |26|};
HOMEPAGE
Please visit the project's homepage athttps://metacpan.org/release/Params-Sah.
SOURCE
Source repository is athttps://github.com/perlancar/perl-Params-Sah.
BUGS
Please report any bugs or feature requests on the bugtracker websitehttps://rt.cpan.org/Public/Dist/Display.html?Name=Params-Sah
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
SEE ALSO
Alternative non-Sah modules:Params::ValidationCompiler (a compiled version ofParams::Validate),Type::Params (fromType::Tiny).
Alternative Sah modules: you can addRinci metadata to your function, then usePerinci::Sub::Wrapper orPerinci::CmdLine to enforce validation. These can do more then schema checking e.g. interargument relationship checking, external dependency checking, etc.
AUTHOR
perlancar <perlancar@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2021, 2020, 2016, 2015 by perlancar@cpan.org.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
Module Install Instructions
To install Params::Sah, copy and paste the appropriate command in to your terminal.
cpanm Params::Sah
perl -MCPAN -e shellinstall Params::Sah
For more information on module installation, please visitthe detailed CPAN module installation guide.