NAME
Sah::Type - Standard types
VERSION
This document describes version 0.9.51 of Sah::Type (from Perl distribution Sah), released on 2022-10-21.
DESCRIPTION
This document specifies Sah standard types.
TYPE: undef
This type does not have any clauses. The only value it knows is the undefined value (like undef
in Perl, or null
in PHP).
ROLE: BaseType
This is the base type role, all Sah types (except undef
) must implement this role.
Clauses
The list below is ordered by priority, from highest to lowest.
defhash_v
Value: float.
Priority: 0 (checked first before everything else).
Category: metadata.
From DefHash. Normally there is no need to set this.
v
Value: float, default: 1.
Priority: 0 (checked first before everything else).
Category: metadata.
From DefHash. Specify Sah version. Should be 1
at the moment.
schema_v
Value: float, default 1.
Priority: 0 (checked first before everything else).
Category: metadata.
Specify schema version. By default assumed to be 1 if not set.
base_v
Value: float, default 1.
Priority: 0 (checked first before everything else).
Category: metadata.
Specify base schema version. By default assumed to be 1 if not set. Using a base schema with a different value will fail. Can be used to force child schemas to update whenever we change our schema. For example:
// schema: vocal
["str", {"in": ["a", "e", "i", "o", "u"]}]
// schema: consonant, defined in terms of "vocal", by
["vocal", {"match": "\\A[a-z]\\z", "in.op": "not"}]
However, if vocal
changes its implementation or structure to:
// the new vocal
["str", {"match": "\\A[aeiou]\\z"}]
then consonant will silently break because of clash (overriding) in the match
clause. To force consonant to fail (so its author can update it, should the authors of vocal
and consonant
are two different persons):
// the new vocal
["str", {"schema_v": 2, "match": "\\A[aeiou]\\z"}]
Since vocal
's schema_v
is now 2, it is not the same as 1 (which is implied by consonant
, having the default value of that of "base_v"). consonant
's author might then update its own implementation to match vocal
:
// the adjusted consonant
["vocal", {"base_v":2, "clset":{"match":"\\A[a-z]\\z"}, "match.op":"not"}]
Notice the matching of consonant
's "base_v" against vocal
's "schema_v". consonant
might also add its own "schema_v":2
so other schemas depending on it are forced to adjust, if needed.
c
Value: any.
Priority: 0 (checked first before anything else).
Category: metadata
Used to store compiler-specific options in its attributes. Example:
"c.perl.use_defined_or": 0
ok
Value: true.
Return value: true (always succeeds).
Priority: 1 (very high). This is processed before all other clauses.
Category: constraint.
Will do nothing. This clause is just a convenience if you want to do nothing (or perhaps just use the attributes of this clause to do things). It is the default in the else
section of the "if" clause.
To force failure, you can use "!ok": true
.
default
Value: any.
Priority: 1 (very high). This is processed before all other clauses except "ok".
Category: default.
Attributes specific to this clause: temp
(bool, default 0, if set to true then default value will only be used during validation and at the end data will not use this value).
Supply a default value.
Example: Given schema ["int", {"req": 1}]
an undef data is invalid, but given schema ["int", {"req": 1, "default": 3}]
an undef data is valid because it will be given default value first.
default_lang
Value: str (locale code)d default en_US
.
Priority: 2 (very high), after "default".
Category: metadata.
From DefHash. Set default language for this schema. Language-dependant attribute values (e.g. "summary", "description") will be assumed to be in the default language.
name
Value: str or [str, str]
.
Priority: 2 (very high), after "default".
Category: metadata.
From DefHash. A short noun (usually one or two words, without any formatting) to name the schema, useful for compiler that transform the schema to human description text.
Aside from string, it can also be a two-element string to set the singular and plural form of the noun.
To store translations, you can use DefHash's alt.lang.*
clause attributes (or its shortcut form using (LANG)
suffix).
Example:
["int", {
"min": 0,
"name": ["positive integer", "positive integers"],
"name(id_ID)": "bilangan positif"
}]
See also: "summary", "description", "tags".
caption
Value: str.
Priority: 2 (very high), after "default".
From DefHash.
summary
Value: str.
Priority: 2 (very high), after "default".
Category: metadata.
From DefHash. A one-line text (about 72 characters maximum, without any formatting) to describe the schema. This is useful, e.g. for manually describing a schema instead of using the human compiler. It can also be used in form field labels.
To store translations, you can use DefHash's alt.lang.*
clause attributes (or its shortcut form using (LANG)
suffix).
Example:
// definition for 'single_dice_throw' schema/type
["int", {
"req": 1,
"summary":
"A number representing result of single dice throw (1-6)",
"summary(id_ID)":
"Bilangan yang menyatakan hasil lempar sebuah dadu (1-6)",
"between": [1, 6]
}]
Without the summary, using a compiler to human text the above schema might be output as the standard, more boring "Integer, value between 1 and 6".
See also: "name", "description", "tags".
description
Value: str.
Priority: 2 (very high), after "default".
Category: metadata.
From DefHash. A longer text (a paragraph or more) to describe the schema, useful e.g. for help/usage text. Text should be in Markdown format.
To store translations, you can use DefHash's alt.lang.*
clause attributes (or its shortcut form using (LANG)
suffix).
Example (using Perl syntax because it supports heredoc):
["array", {
name => 'http_headers',
description => <<EOT,
HTTP headers should be specified as an array of 2-element arrays (pairs). Each
pair should contain header name in the first element (all lowercase, *-*
written as *_*) and header value in the second element.
Example:
[["content_type","text/html"], ["accept","text/html"], ["accept","*/*"]]
EOT
req => 1,
of => 'http_header',
},
{}]
See also: "name", "summary", "tags".
tags
Value: array of str.
Priority: 2 (very high), after "default".
Category: metadata.
From DefHash. A list of tags, can be used to categorize schemas.
See also: "name", "summary", "description".
req
Value: bool.
Priority: 3 (very high), executed after "default".
Category: constraint.
If set to 1, require that data be defined. Otherwise, allow data to be undef (the default behaviour).
By default, undef will pass even elaborate schema, e.g. ["int", {"min": 0, "max": 10, "div_by": 3}]
will still pass an undef. However, undef will not pass ["int": {"req": 1}]
.
This behaviour is much like NULLs in SQL: we *can't* (in)validate something that is unknown/unset.
See also: "forbidden"
forbidden
Value: bool.
Priority: 3 (very high), executed after "default".
Category: constraint.
This is the opposite of "req", requiring that data be not defined (i.e. undef).
Given schema ["int", {"forbidden": 1}]
, a non-undef value will fail. Another example: the schema ["int", {"req": 1, "forbidden": 1}]
will always fail due to conflicting clauses.
See also: "req"
prefilters
Value: array of (filter rule name)s, or ([filter rule name, argument hash]).
Priority: 10 (high). Run after "default" and "req"/"forbidden".
Category: filter.
Attributes specific to this clause: temp
(bool, default 0, if set to true then prefiltered value will only be used during validation and at the end of the clause set data will not use this value).
clause
Value: 2-element array [CLNAME, CLVAL]
.
Return value: clause return value.
Priority: 50 (normal)
Category: constraint.
Evaluate a clause. Example:
["int", "clause", ["div_by", 2]] // equivalent to ["int", "div_by", 2]
This clause is useful when combined with the .op
attribute. Example:
["int", "clause|", [["div_by", 2], ["xmin", 10]]]
// equivalent to:
// ["int", "clause", [["div_by", 2], ["xmin", 10]], "clause.op", "or"]
The above schema says that the integer needs to be divisible by 2 or larger than 10.
clset
Value: hash.
Return value: int (number of successful clauses + 1) on success, false on failure.
Priority: 50 (normal)
Category: constraint.
Evaluate a clause set. Note that return value adds 1 to the number of successful clauses to avoid returning 0 (evaluates to false). And it will only be returned if clause is successful. Otherwise false (0) will be returned. Example:
// require that data is between 1 and 10.
// equivalent to ["int", "min", 1, "max", 10]
["int", "clset", {"min": 1, "max": 10}]
// require that either data is between 1 and 10, or 90 and 100
["int", "clset|", [{"min": 1, "max": 10}, {"min": 90, "max": 100}]]
See also: "clause".
check
Value: expression string.
Return value: result of evaluated expression
Priority: 50 (normal)
Category: constraint.
Evaluate expression, which must evaluate to a true value for this clause to succeed. Examples:
// require that string is a palindrome, using a Sah function
["str", "check", "is_palindrome($_)"]
// require that the *length of* string is a prime number
["str", "check", "is_prime(len($_))"]
prop
Value: 2-element str [PROP, SCHEMA]
.
Return value: bool
Priority: 50 (normal)
Category: constraint
Validate property against a schema. Example:
// require that the *length of* string is divisible by 2
["str", "prop", ["len", ["int", "div_by", 2]]]
See also: "check_prop"
check_prop
Value: 2-element str [PROP, SCHEMA]
.
Return value: result of evaluated expression
Priority: 50 (normal)
Category: constraint
Just like "check", but instead of checking data itself, check property PROP
. Example:
// require that the *length of* string is a prime number
["str", "check_prop", ["len", "is_prime($_)"]]
// check that the email's Subject header is a palindrome
["email", "check_prop", [["headers", "subject"], "is_palindrome($_)"]]
See also: "prop"
if
Value:
[COND, THEN] -> any
[COND, THEN, ELSE] -> any
Return value: if condition is true, then the THEN
result, otherwise the ELSE
result.
Priority: 50 (normal)
Category: constraint.
A generic condition clause. COND
, THEN
, and ELSE
are either boolean values, expressions (if they are string) or a clause set (if they are hash) or a schema (if they are array). COND
is evaluated, if the result is true then THEN
is evaluated, otherwise ELSE
is evaluated. ELSE
is optional.
Examples:
// forbid the string to be lowercase
"if": [{"match": "^[a-z]$"}, false]
// if string is lowercase, it must be a palindrome
"if": [{"match": "^[a-z]$"}, "is_palindrome($_)"]
// if string is lowercase, it must be a palindrome, otherwise it must be longer
// than 3 characters.
"if": [{"match": "^[a-z]$"}, "is_palindrome($_)", "len($_) > 3"]
// require the length of the string to be an even number
"if": [{"prop": ["len", ["int", "div_by", 2]]}, true}
// if string is a palindrome, then require it to have length > 5
"if": [{"check": "is_palindrome($_)"}, ["len", ["int", "xmin": 5]]]
Note that you have to write schema in array form instead of string form, to avoid ambiguity with expression:
// parsed as expression, wrong!
"if": ["int", true]
// correct
"if": [["int"], true]
postfilters
Value: array of (filter rule name)s, or ([filter rule name, argument hash]).
Priority: 90 (very low). Run after all other clauses.
Category: filter.
From here on, the data will be permanently set to the postfiltered value.
examples
Value: array of (non-hash values|defhash)
Priority: 99 (informational)
Category: metadata.
A list of sample valid values. Can be used, e.g. for documentation, testing, or completion. Each element is sample value, except when value is a hash then it is assumed as a defhash (with the actual value in the value
property). So if your sample value happens to be a hash like {}
, it has to be specified as {"value":{}}
.
Note that this clause is informational only and does not require the value to be in one of the specified examples (use "in" clause for this purpose).
See also: "invalid_examples", "in".
invalid_examples
Value: array of (non-hash values|defhash)
Priority: 99 (informational)
Category: metadata.
This is the counterpart of "examples", containing examples of invalid values.
See also: "examples".
ROLE: Comparable
This is the comparable type role. All types which have comparable values must implement this role. Most types implement this role, including str, all number types, etc.
Clauses
in
Value: array of any values.
Priority: 50 (normal)
Category: constraint
Require that the data be one of the specified choices.
Examples:
["int", {"in": [1, 2, 3, 4, 5, 6]}] // single dice throw value
["str", {"!in": ["root", "admin", "administrator"]}] // forbidden usernames
To provide sample valid values that are not binding, use the "examples" clause.
See also: "examples", "match" (for type str), "has" (for HasElems types).
is
Value: any.
Priority: 50 (normal)
Category: constraint
Require that the data is the same as VALUE. Will perform a numeric comparison for numeric types, or stringwise for string types, or deep comparison for deep structures.
Examples:
["int", {"is": 3}]
["int", {"is&": [1, 2, 3, 4, 5, 6]}] // effectively the same as 'in'
ROLE: HasElems
This is the role for types that have the notion of elements/length. It provides clauses like "max_len", "len", "len_between", "each_elem", etc. It is used by array, hash, and also str.
Properties
len (HasElems property)
Number.
elems (HasElems property)
Array.
indices (HasElems property)
Array.
Clauses
max_len
Value: uint.
Priority: 50 (normal)
Category: constraint
Requires that the data have at most the specified number of elements.
Example:
["str", {"req": 1, "max_len": 10}] // string with at most 10 characters
min_len
Value: uint.
Priority: 50 (normal)
Category: constraint
Requires that the data have at least the specified number of elements.
Example:
["array", {"min_len": 1}] // define an array with at least one element
len_between
Value: 2-element array ([NUM_MIN, NUM_MAX]
)
Priority: 50 (normal)
Category: constraint
A convenience clause that combines "min_len" and "max_len".
Example, the two schemas below are equivalent:
["str", {"len_between": [1, 10]}]
["str", {"min_len": 1, "max_len": 10}]
len
Value: uint.
Priority: 50 (normal)
Category: constraint
Requires that the data have exactly NUM elements.
has
Value: any.
Priority: 50 (normal)
Category: constraint
Requires that the data contains the element. This is the counterpart of the "in" clause.
Examples:
// requires that array has element x
["array", {"has": "x"}]
// requires that array has elements 'x', 'y', and 'z'
["array", {"has&": ["x", "y", "z"]}]
// requires that string does not have character 'x'
["str", {"!has": "x"}]
uniq
Value: bool.
If set to 1, require that the element values be unique (like in a set). If set to 0, require that there are duplicates in the elements. For example, given this schema:
["array", "uniq", true]
this data passes: [1, 2, 3]
but this one does not: [1, 2, 1]
.
each_elem
Value: schema.
Priority: 50 (normal)
Category: constraint, looping
Requires that every element of data validate to the specified schema. The first element that fails the schema will terminate the loop.
Examples:
["array", {"each_elem": "int"}]
["array", {"of": "int"}] // same thing, "of" is the same as "each_elem"
The above specifies an array of integers.
["hash", {"each_elem": ["str", {"match": "^[A-Za-z0-9]+$" }]}]
The above specifies hash with alphanumeric-only values.
check_each_elem
Value: expression string.
Priority: 50 (normal)
Category: constraint, looping
Just like "each_elem" but instead of using schema, each element is tested using expression.
each_index
Value: schema.
Priority: 50 (normal)
Category: constraint, looping
Like "each_elem" but iterates over the indices. For type like array, this is 0, 1, ... N. For hash, this is the keys of hash.
check_each_index
Value: expression string.
Priority: 50 (normal)
Category: constraint, looping
Like "each_index" but instead of using schema, each index is tested using expression.
exists
Value: schema.
Priority: 50 (normal)
Category: constraint, looping
Test that there is at least one element of data that validates to the schema. That element is returned. Be careful to not return element which has the value which evaluates to false.
check_exists
Value: expression string.
Priority: 50 (normal)
Category: constraint, looping
Just like "exists" but instead of using schema, each element is tested using expression.
ROLE: Sortable
This is the type role for sortable types. It provides clauses like "min", "max", and "between". It is used by many types, for example str, all numeric types, etc.
Clauses
min
Value: any.
Require that the value is not less than some specified minimum (equivalent in intention to the Perl string ge
operator, or the numeric >=
operator).
Example:
["int", "min", 0] // specify positive numbers
xmin
Value: any.
Require that the value is not less nor equal than some specified minimum (equivalent in intention to the Perl string gt
operator, or the numeric >
operator). The x
prefix is for "exclusive".
max
Value: any.
Require that the value is less or equal than some specified maximum (equivalent in intention to the Perl string le
operator, or the numeric <=
operator).
xmax
Value: any.
Require that the value is less than some specified maximum (equivalent in intention to the Perl string lt
operator, or the numeric <
operator). The x
prefix is for "exclusive".
between
Value: 2-element string ([ANY_MIN, ANY_MAX]
)
A convenient clause to combine "min" and "max".
Example, the following schemas are equivalent:
["float", {"between": [0.0, 1.5]}]
["float", {"min": 0.0, "max": 1.5}]
xbetween
Value: 2-element string ([ANY_MIN, ANY_MAX]
)
A convenient clause to combine "xmin" and "xmax".
TYPE: buf
buf
stores binary data. Elements of buf data are bytes. It is derived from str.
TYPE: num
num
stores numbers. This type assumes the Comparable and Sortable roles.
TYPE: float
float
stores real (floating-point) numbers. This type is derived from num.
Clauses
is_nan
Value: bool.
If true, require that number is a NaN (e.g. "NaN" or "-NaN" in Perl). If false, forbid that the number is a NaN.
is_inf
Value: bool.
If true, require that number is a positive or negative infinity (e.g. "Inf" or "-Infinity" in Perl). If false, forbid that the number is an infinity (which can mean a finite number or a NaN).
is_pos_inf
Value: bool.
If true, require that number is a positive infinity (e.g. "Inf" or "+Infinity" in Perl). If false, forbid that number is a positive infinity (which can mean a finite number, negative infinity, or a NaN).
is_neg_inf
Value: bool.
If true, require that number is a negative infinity (e.g. "-Inf" or "-Infinity" in Perl). If false, forbid that number is a negative infinity (which can mean a finite number, positive infinity, or a NaN).
TYPE: int
int
stores integers. This type is derived from num.
Clauses
mod
Value: 2-element array of ints ([INT1, INT2]
).
Require that (data mod INT1
) equals INT2
. For example, "mod": [2, 1]
effectively specifies odd numbers.
div_by
Value: int.
Require that data is divisible by the specified number. This is effectively just a shortcut for "mod": [INT, 0]
.
Example: Given schema ["int", {"div_by": 2}]
, null, 0, 2, 4, and 6 are valid but 1, 3, 5 are not.
TYPE: str
str
stores strings (text). This type assumes the Comparable, Sortable, and HasElems roles (the elements are individual characters, the indices are integers from 0 to (length of string)-1). Default encoding is utf8.
Clauses
encoding
Value: str, default utf8
.
Specify encoding. Currently the only supported value is utf8
.
match
Value: string (regex) or hash of regexes (REGEX|{COMPILER=>REGEX, ...}
)
Require that string match the specified regular expression.
Since regular expressions might not be 100% compatible from language to language, instead of avoiding the use of regex entirely, you can specify different regex for each target language, e.g.:
["str", {"match": {
"js": "...",
"perl": "...",
"python": "..."
}}]
To match against multiple regexes:
// string must match a, b, and c
["str", {"match&": ["a", "b", "c"]}]
// string must match either a or b or c
["str", {"match|": ["a", "b", "c"]}
// string must NOT match a
["str", {"!match": "a"}]
// string must NOT match a nor b nor c (i.e. must match none of those)
["str", {"match": [a, b, c], "match.op": "none"}]
is_re
Value: bool.
If value is true, require that the string be a valid regular expression string. If value is false, require that the string not be a valid regular expression string.
TYPE: cistr
Just like str, but comparison between values will be done case-insensitively.
TYPE: bool
Boolean type. This type assumes the Comparable and Sortable roles.
Clauses
is_true
Value: bool.
Require that value is true. This is a more portable way than comparing to a value using "is". To require that value is false, set this clause to a false value. Alternatively you can also use "!is_true": 1
.
TYPE: array
Array type. This type assumes the Comparable and HasElems roles (the elements are indexed by integers starting from 0).
Clauses
elems
Value: array of schema.
Attributes: create_default
(bool, default: 1).
Specify schemas for each element of the array. Example:
["array", "elems", ["int*", "float"]]
Valid values include [1]
, [1, undef]
, [1, 1.1]
, [1, 1.1, "foo"]
. Invalid values include []
(first element is a required int), [1, "foo"]
(second element does not validate).
If there are not enough elements in the data, they will be assumed to be null
(undefined value). Extra elements in the data are ignored.
The .create_default
attribute regulates whether missing elements should be set with default values if they do not exist in the data. Example:
["array", "elems", ["int*", ["float", "default", 2]]]
In the last example, [1]
will become [1, 2]
after validation. However with:
["array",
"elems", ["int*", ["float", "default", 2]],
"elems.create_default", 0]
[1]
will still become [1]
after validation. In both cases, [1, undef]
will become [1, 2]
.
of
Value: schema.
This is just an alias to "each_elem".
TYPE: hash
Hash (a.k.a. dictionary) type. This type assumes the "ROLE: Comparable" in Comparable and HasElems roles (the elements are hash values, the indices are hash keys).
Properties
keys (hash property)
Value: array.
Alias for HasElems's "indices".
values (hash property)
Value: array.
Clauses
keys
Value: hash.
Attributes: restrict
(bool, default: 1), create_default
(bool, default: 1).
Specify schema for specific pair value. Also, by default, restrict keys of hash to the list specified in this clause, except if the .restrict
attribute is set to false. Example:
["hash*",
"keys", {
"name": "str",
"address": ["any", "of", ["str", ["array", "of", "str"]]],
"email": "email_address"
},
]
The above schema requires data to be a hash with keys name
, address
, email
. None of the keys are required to be present (use "req_keys" for that), but other keys are not allowed.
Another example:
["hash",
"keys", {"a": "int", "b": "str", "c": "float"},
"keys.restrict", 0
]
The above schema specifies a hash with definition for the value of its a
, b
, and c
keys. But other keys like d
are allowed since the "keys" clause is set to not restrict keys.
The .create_default
attribute regulates whether keys should be created with default values if they do not exist in the data. For example:
["hash", "keys": {"a": "int", "b": ["int", "default": 2]}]
Given data {}
, by default it will be given defaults so it becomes {"b": 2}
. a
is not created because it does not have a default value. However, if .create_default
is set to false:
["hash",
"keys", {"a": "int", "b": ["int", "default": 2]},
"keys.create_default", 0
]
then {}
will still become {}
after validation. In both cases, {"b": null}
will still become {"b": 2}
.
re_keys
Value: hash
Attributes: restrict
(bool, default: 1)
Just like keys
, but specifies schemas for keys which match regexes. Example:
["hash", "re_keys", {"^[A-Za-z]": "str", "^[0-9]": "int"}]
The above schema specifies that for keys which begin with a letter the values must be strings, and for keys which begin with a digit the values must be integers. These hashes validate: {}
, {"a": "x", "b": 1, "1": 1}
. These hashes do not validate: {"1": "x"}
, {"#": "x"}
(key does not match any keys in "re_keys").
req_keys
Value: array
Specify which keys are required to be exist. Note that the values for those keys are not required to be defined (use "keys" for that). Example:
["hash", "req_keys", ["a", "b"]]
The above schema specifies that hash needs to have some keys, but the value can be null. This hash will validate: {"a": 1, "b": null}
. However, given this schema:
["hash", "req_keys", ["a", "b"], "keys", {"a": "int", "b": "int*"}]
the previous hash will not validate since the value for b
is required.
Note: you can also use the "keys" property to express the same thing, but "req_keys" is more convenient:
["hash", "prop", ["keys", ["array", "has&", ["a", "b"]]]]
See also: "allowed_keys", "forbidden_keys".
allowed_keys
Value: array
Specify which keys are allowed (can exist). Unlike "req_keys", keys specified in the value need not exist. Example:
["hash", "allowed_keys", ["a", "b"]]
Then hashes {}
, {"a":1}
, {"a":1,"b":2}
all pass, but {"a":1,"c":3}
fails because it contains keys outside the allowed list.
Note: you can also use the "keys" property to express the same thing, but "allowed_keys" is more convenient:
["hash", "prop", ["keys", ["array", "each_elem", ["str", "in", ["a", "b"]]]]]
See also: "req_keys", "forbidden_keys".
allowed_keys_re
Value: regex
Like "allowed_keys" but using regular expression.
forbidden_keys
Value: array
Specify which keys are forbidden (must not exist). Example:
["hash", "forbidden_keys", ["a", "b"]]
Then hashes {}
, {"c":1}
all pass, but {"a":1,"c":3}
fails because it contains keys in the forbidden list.
Note: you can also use the keys
property to express the same thing, but "forbidden_keys" is more convenient:
["hash", "prop", ["keys", ["array", "each_elem", ["str", "!in", ["a", "b"]]]]]
See also: "req_keys", "allowed_keys".
forbidden_keys_re
Value: regex
Like "forbidden_keys" but using regular expression.
each_key
Alias for "each_index".
each_value
Alias for "each_elem".
check_each_key
Alias for "check_each_index".
check_each_value
Alias for "check_each_elem".
choose_one_key
Value: array of str.
Specify that hash contains at most one out of a list of key names. Example:
["hash", "choose_one_key", ["exclude", "exclude_from"]]
Hash can contain either "exclude" or "exclude_from" but not both.
choose_one
Alias for "choose_one_key".
choose_all_keys
Value: array of str.
Specify that if hash contains any one of keys in a given list of key names, then hash must contain all of those keys. Example:
["hash", "choose_all_keys", ["password", "confirmation"]]
When hash contains "password", it must also contain "confirmation". And vice versa.
choose_all
Alias for "choose_all_keys".
choose_some_keys
Value: 3-element array ([MIN, MAX, KEYS]
).
Require that hash has between MIN
and MAX
of keys in KEYS
.
req_one_key
Value: array of str.
Specify that only exactly one key is required to exist. Example:
["hash", "req_one_key", ["input_value", "input_file"]] // either specify input value directly, or specify path to file that contains the value
When the two keys both exist, the clause fails.
req_one
Alias for "req_one_key".
req_all_keys
Alias for "req_keys".
req_all
Alias for "req_keys".
req_some_keys
Value: 3-element array ([MIN, MAX, KEYS]
)
Specify that between MIN
and MAX
of keys in KEYS
are required.
req_some
Alias for "req_some_keys".
dep_any
Value: 2-element array ([ STR|ARRAY[STR], ARRAY[STR] ]
)
Specify that the first argument (either a string containing a key name, or a list of key names) can only exist when one of the keys given in the second argument exists. Example:
["hash", "dep_any", ["postcode", ["address"]]]
The "postcode" key can only be specified if "address" key exists.
Another example:
["hash", "dep_any", ["input_format", ["input_value", "input_file"]]
If "input_value" or "input_file" exists, then "input_format" is allowed to be specified.
Yet another example:
["hash", "dep_any", [["input_format", "input_is_yaml", "input_is_json"], ["input_value", "input_file"]]
If either "input_value" or "input_file" exists, then one of "input_format", "input_is_yaml", "input_is_json" is allowed to be specified.
dep_all
Value: 2-element array ([ STR|ARRAY[STR], ARRAY[STR] ]
)
Specify that the first argument (either a string containing a key name, or a list of key names) can only exist when all of the keys given in the second argument exist. Example:
["hash", "dep_all", ["postcode", ["address"]]]
In the above example, you can also use "dep_any" clause for the same effect since there is only one key to depend on. Another example:
["hash", "dep_all", ["postcode", ["address", "city"]]
In the above example, "postcode" can only be specified when both "address" and "city" exist. Yet another example:
req_dep_any
Value: 2-element array ([ STR|ARRAY[STR], ARRAY[STR] ]
)
Specify that the first argument (either a string containing a key name, or a list of key names) is required when one of the keys given in the second argument exist.
req_dep_all
Value: 2-element array ([ STR|ARRAY[STR], ARRAY[STR] ]
)
Specify that the first argument (either a string containing a key name, or a list of key names) is required when all of the keys given in the second argument exist.
TYPE: any
A type to specify alternate schemas, or a type that allows any value.
Clauses
of (any)
Value: array of schemas
Specify the schema(s) where the value will need to be valid to at least one of them.
TYPE: all
A type to specify co-schemas (all schemas that must be validated to value).
Clauses
of (all)
Value: array of schemas
Specify the schema(s) where the value will need to be valid to all of them.
TYPE: obj
Object.
Properties
meths (obj property)
attrs (obj property)
Clauses
can
Value: str.
isa
Value: str.
TYPE: date (not yet specified)
TYPE: datenotime (not yet specified)
TYPE: datetime (not yet specified)
TYPE: duration (not yet specified)
TYPE: timeofday (not yet specified)
HOMEPAGE
Please visit the project's homepage at https://metacpan.org/release/Sah.
SOURCE
Source repository is at https://github.com/perlancar/perl-Sah.
SEE ALSO
AUTHOR
perlancar <perlancar@cpan.org>
CONTRIBUTING
To contribute, you can send patches by email/via RT, or send pull requests on GitHub.
Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via:
% prove -l
If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond that are considered a bug and can be reported to me.
COPYRIGHT AND LICENSE
This software is copyright (c) 2022, 2020, 2019, 2017, 2016, 2015, 2014, 2013, 2012 by perlancar <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.
BUGS
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=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.