JSON-Schema-Modern

 view release on metacpan or  search on metacpan

t/formats.t  view on Meta::CPAN

          keywordLocation => '/items',
          error => 'subschema is not valid against all items',
        },
      ],
    },
    'pure_integer format with type',
  );

  is_equal(
    $js->evaluate(
      [
        (map $decoder->decode($_),
          '"hello"',  # string, will not apply format
          '3.1',      # number, will apply format
          '3.0',      # ""
          '3',        # ""
        ),
        bless(\$int, 'Local::MyInteger'), # blessed type, will not apply format
      ],
      {
        items => {
          format => 'pure_integer',
        },
      },
    )->TO_JSON,
    {
      valid => false,
      errors => [
        # strings are not applied to the format
        {
          instanceLocation => '/1',
          keywordLocation => '/items/format',
          error => 'not a valid pure_integer number',
        },
        {
          instanceLocation => '/2',
          keywordLocation => '/items/format',
          error => 'not a valid pure_integer number',
        },
        {
          instanceLocation => '',
          keywordLocation => '/items',
          error => 'subschema is not valid against all items',
        },
      ],
    },
    'pure_integer format without type',
  );
};

subtest 'formats supporting multiple core types' => sub {
  # this is int64 from the OAI format registry: https://spec.openapis.org/registry/format/
  my $js = JSON::Schema::Modern->new(
    validate_formats => 1,
    format_validations => +{
      # a signed 64-bit integer; see https://spec.openapis.org/api/format.json
      int64 => +{ type => ['number', 'string'], sub => sub ($value) {
        my $type = get_type($value);
        return if not grep $type eq $_, qw(integer number string);
        $value = Math::BigInt->new($value) if $type eq 'string';
        return if $value eq 'NaN';
        # using the literal numbers rather than -2**63, 2**63 -1 to maintain precision
        $value >= Math::BigInt->new('-9223372036854775808') && $value <= Math::BigInt->new('9223372036854775807');
      } },
    },
  );

  my @values = (
    '{}',     # object is valid
    '[]',     # array is valid
    'true',   # boolean is valid
    'null',   # null is valid

    # string
    '"-9223372036854775809"', # 4: out of bounds
    '"-9223372036854775808"', # minimum value
    '"-9223372036854775807"', # within bounds
    '"0"',
    '"9223372036854775806"',  # within bounds
    '"9223372036854775807"',  # maximum value
    '"9223372036854775808"',  # out of bounds
    '"Inf"',
    '"NaN"',

    # number
    '-9223372036854775809',   # 13: out of bounds
    '-9223372036854775808',   # minimum value; difficult to use on most architectures without Math::BigInt
    '-9223372036854775807',   # within bounds
    '0',
    '9223372036854775806',    # within bounds
    '9223372036854775807',    # maximum value
    '9223372036854775808',    # 19: out of bounds
    # numeric Inf and NaN are not valid JSON
  );

  # note: results may vary on 32-bit architectures when not using Math::BigFloat
  foreach my $decoder (
      JSON::Schema::Modern::_JSON_BACKEND()->new->allow_nonref(1)->utf8(0),
      JSON::Schema::Modern::_JSON_BACKEND()->new->allow_nonref(1)->utf8(0)->allow_bignum(1)) {
    is_equal(
      $js->evaluate(
        [ map $decoder->decode($_), @values ],
        {
          items => {
            format => 'int64',
          },
        },
      )->TO_JSON,
      {
        valid => false,
        errors => [
          (map +{
            instanceLocation => "/$_",
            keywordLocation => '/items/format',
            error => 'not a valid int64 number, string',
          },
          4, 10, 11, 12, 13, 19),
          {
            instanceLocation => '',
            keywordLocation => '/items',
            error => 'subschema is not valid against all items',
          },
        ],
      },
      'int64 format without type - accepts both numbers and strings',
    );
  }
};

subtest 'stringy numbers with a numeric format' => sub {
  my $js = JSON::Schema::Modern->new(
    validate_formats => 1,
    stringy_numbers => 1,
    format_validations => +{
      mult_5 => +{ type => 'number', sub => sub { ($_[0] % 5) == 0 } },
    },
  );

  is_equal(
    my $res = $js->evaluate(
      [
        3,
        '3',
        5,
        '5',
        'abc',
      ],
      { items => { format => 'mult_5' } },
    )->TO_JSON,
    {
      valid => false,
      errors => [
        {



( run in 1.777 second using v1.01-cache-2.11-cpan-39bf76dae61 )