Data::Sah::Coerce - Coercion rules for Data::Sah

    This document describes version 0.049 of Data::Sah::Coerce (from Perl
    distribution Data-Sah-Coerce), released on 2020-05-24.

     use Data::Sah::Coerce qw(gen_coercer);

     # a utility routine: gen_coercer
     my $c = gen_coercer(
         type               => 'date',
         coerce_to          => 'DateTime',
         coerce_rules       => ['From_str::natural'],  # explicitly enable a rule, etc
         # return_type      => 'str+val',              # default is 'val'

     my $val = $c->(123);          # unchanged, 123
     my $val = $c->(1463307881);   # becomes a DateTime object
     my $val = $c->("2016-05-15"); # becomes a DateTime object
     my $val = $c->("2016foo");    # unchanged, "2016foo"

    This distribution contains a standard set of coercion rules for
    Data::Sah. It is separated from the "Data-Sah" distribution and can be
    used independently.

    A coercion rule is put in
    IPTION" module, for example:
    Data::Sah::Coerce::perl::To_date::From_float::epoch for converting date
    from integer (Unix epoch) or
    Data::Sah::Coerce::perl::To_date::From_str::iso8601 for converting date
    from ISO8601 strings like "2016-05-15".

    Basically, a coercion rule will provide an expression ("expr_match")
    that evaluates to true when data can be coerced, and an expression
    ("expr_coerce") to actually coerce/convert data to the target type. This
    rule can be combined with other rules to form the final coercion code.

    The module must contain "meta" subroutine which must return a hashref
    that has the following keys ("*" marks that the key is required):

    *   v* => int (default: 1)

        Metadata specification version. From DefHash. Currently at 4.

        History: bumped from 3 to 4 to remove "enable_by_default" property.
        Now the list of standard (enabled-by-default) coercion rules is
        maintained in Data::Sah::Coerce itself. This allows us to skip
        scanning all Data::Sah::Coerce::* coercion modules installed on the
        system. Data::Sah::Coerce still accepts version 3; it just ignores
        the "enable_by_default" property.

        History: bumped from 2 to 3 to allow coercion expression to return
        error message explaining why coercion fails. The "might_die"
        metadata property is replaced with "might_fail". When "might_fail"
        is set to true, "expr_coerce" must return array containing error
        message and coerced data, instead of just coerced data.

        History: Bumped from 1 to 2 to exclude old module names.

    *   summary => str

        From DefHash.

    *   might_fail => bool (default: 0)

        Whether coercion might fail, e.g. because of invalid input. If set
        to 1, "expr_coerce" key that the "coerce()" routine returns must be
        an expression that returns an array (envelope) of "(error_msg,
        data)" instead of just coerced data. Error message should be a
        string that is set when coercion fails and explains why. Otherwise,
        if coercion succeeds, the error message string should be set to
        undefined value.

        An example of a rule like this is coercing from string in the form
        of "YYYY-MM-DD" to a DateTime object. The rule might match any
        string in the form of "/\A(\d{4})-(\d{2})-(\d{2})\z/" while it might
        not be a valid date.

        This is used for coercion rules that act as a data checker.

    *   prio => int (0-100, default: 50)

        This is to regulate the ordering of rules. The higher the number,
        the lower the priority (meaning the rule will be put further back).
        Rules that are computationally more expensive and/or match more
        broadly in general should be put further back (lower priority,
        higher number).

    *   precludes => array of (str|re)

        List the other rules or rule patterns that are precluded by this
        rule. Rules that are mutually exclusive or pure alternatives to one
        another (e.g. date coercien rules From_str::natural vs
        From_str::flexible both parse natural language date string; there is
        usually little to none of usefulness in using both; besides, both
        rules match all string and dies when failing to parse the string. So
        in "From_str::natural" rule, you'll find this metadata:

         precludes => [qr/\A(From_str::alami(_.+)?|From_str::natural)\z/]

        and in "From_str::flexible" rule you'll find this metadata:

         precludes => [qr/\A(From_str::alami(_.+)?|From_str::flexible)\z/]

        Also note that rules which are specifically requested to be used
        (e.g. using "x.perl.coerce_rules" attribute in Sah schema) will
        still be precluded.

    The module must also contain "coerce" subroutine which must generate the
    code for coercion. The subroutine must accept a hash of arguments ("*"
    indicates required arguments):

    *   data_term => str

    *   coerce_to => str

        Some Sah types are "abstract" and can be represented using a choice
        of several actual types in the target programming language. For
        example, "date" can be represented in Perl as an integer (Unix epoch
        value), or a DateTime object, or a Time::Moment object.

        Not all target Sah types will need this argument.

    The "coerce" subroutine must return a hashref with the following keys
    ("*" indicates required keys):

    *   expr_match => str

        Expression in the target language to test whether the data can be
        coerced. For example, in
        "Data::Sah::Coerce::perl::To_date::From_float::epoch", only integers
        ranging from 10^8 to 2^31 are converted into date. Non-integers or
        integers outside this range are not coerced.

    *   expr_coerce => str

        Expression in the target language to actually convert data to the
        target type.

    *   modules => hash

        A list of modules required by the expressions.

    Basically, the "coerce" subroutine must generates a code that accepts a
    non-undef data and must convert this data to the desired type/format
    under the right condition. The code to match the right condition must be
    put in "expr_match" and the code to convert data must be put in

    Program/library that uses Data::Sah::Coerce can collect rules from the
    rule modules then compose them into the final code, something like (in

     if (data is undef) {
       return undef;
     } elsif (data matches expr-match-from-rule1) {
       return expr-coerce-from-rule1;
     } elsif (data matches expr-match-from-rule2) {
       return expr-coerce-from-rule1;
     } else {
       # does not match any expr-match
       return original data;

  $Log_Coercer_Code => bool (default: from ENV or 0)
    If set to true, will log the generated coercer code (currently using
    Log::ger at trace level). To see the log message, e.g. to the screen,
    you can use something like:

     % TRACE=1 perl -MLog::ger::LevelFromEnv -MLog::ger::Output=Screen \
         -MData::Sah::Coerce=gen_coercer -E'my $c = gen_coercer(...)'


     gen_coercer() -> any

    Generate coercer code.

    This is mostly for testing. Normally the coercion rules will be used
    from Data::Sah.

    This function is not exported by default, but exportable.

    No arguments.

    Return value: (any)

    Set default for $Log_Coercer_Code.

    Please visit the project's homepage at

    Source repository is at

    Please report any bugs or feature requests on the bugtracker website

    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.



    App::SahUtils, including coerce-with-sah to conveniently test coercion
    from the command-line.

    perlancar <>

    This software is copyright (c) 2020, 2019, 2018, 2017, 2016 by

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