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 )