Skip Menu |

This queue is for tickets about the JSON-Schema CPAN distribution.

Report information
The Basics
Id: 80083
Status: resolved
Priority: 0/
Queue: JSON-Schema

People
Owner: perl [...] toby.ink
Requestors: DAVIDIAM [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 0.012
Fixed in: (no value)



Subject: Union data type validation
union data type validation broken because it doesn't check for the ref cases before it checks for the type match cases. Also doesn't handle boolean checks against null values. Patch for Helper.pm and reasonably complete test for union types attached.
Subject: 05union.t.txt
use Test::More; use strict; use warnings; use JSON::Schema; #primitive types are object, array, string, number, integer, boolean, null or any my $schema1 = JSON::Schema->new( { type => 'object' , additionalProperties => 0 , properties => { test => { type => [ 'boolean', 'integer' ] , required => 1 } } } ); my $schema2 = JSON::Schema->new( { type => 'object' , additionalProperties => 0 , properties => { test => { type => [ { type=>"object" , additionalProperties => 0 , properties=> { dog => { type=>"string", required=>1 } } } , { type => "object" , additionalProperties => 0 , properties => { sound => { type => 'string' , enum => ["bark","meow","squeak"] , required => 1 } } } ] , required => 1 } } }); my $schema3 = JSON::Schema->new( { type => 'object' , additionalProperties => 0 , properties => { test => { type => [ qw/object array string number integer boolean null/ ], required => 1 } } } ); my $result = $schema1->validate({ test => "strang" }); ok !$result->valid, 'boolean or integer against string' or map { diag "reason: $_" } $result->errors; $result = $schema1->validate({ test => 1 }); ok $result->valid, 'boolean or integer against integer' or map { diag "reason: $_" } $result->errors; $result = $schema1->validate({ test => [ 'array' ] }); ok not($result->valid), 'boolean or integer against array' or map { diag "reason: $_" } $result->errors; $result = $schema1->validate({ test => { object => 'yipe' } }); ok !$result->valid, 'boolean or integer against object' or map { diag "reason: $_" } $result->errors; $result = $schema1->validate({ test => 1.1 }); ok not($result->valid), 'boolean or integer against number' or map { diag "reason: $_" } $result->errors; $result = $schema1->validate({ test => !!1 }); ok $result->valid, 'boolean or integer against boolean' or map { diag "reason: $_" } $result->errors; $result = $schema1->validate({ test => undef }); ok !$result->valid, 'boolean or integer against null' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => { dog => "woof" } }); ok $result->valid, 'object or object against object a' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => { sound => "meow" } }); ok $result->valid, 'object or object against object b nested enum pass' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => { sound => "oink" } }); ok not($result->valid), 'object or object against object b enum fail' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => { audible => "meow" } }); ok !$result->valid, 'object or object against invalid object' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => 2 }); ok !$result->valid, 'object or object against integer' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => 2.2 }); ok !$result->valid, 'object or object against number' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => !1 }); ok !$result->valid, 'object or object against boolean' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => undef }); ok !$result->valid, 'object or object against null' or map { diag "reason: $_" } $result->errors; $result = $schema2->validate({ test => { dog => undef } }); ok not($result->valid), 'object or object against object a bad inner type' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => { dog => undef } }); ok $result->valid, 'all types against object' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => [ 'dog' ] }); ok $result->valid, 'all types against array' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => 'dog' }); ok $result->valid, 'all types against string' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => 1.1 }); ok $result->valid, 'all types against number' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => 1 }); ok $result->valid, 'all types against integer' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => 1 }); ok $result->valid, 'all types against boolean' or map { diag "reason: $_" } $result->errors; $result = $schema3->validate({ test => undef }); ok $result->valid, 'all types against null' or map { diag "reason: $_" } $result->errors; done_testing;
Subject: json-schema-helper-patch.txt
--- ./lib/JSON/Schema/Helper.pm 2012-05-03 17:59:26.000000000 -0400 +++ /usr/local/share/perl/5.10.0/JSON/Schema/Helper.pm 2012-10-09 17:10:25.000000000 -0400 @@ -118,17 +118,12 @@ # and ($type eq 'null' ? $self->jsIsNull($value) : $self->jsMatchType($type, $value)) # and !(ref $value eq 'ARRAY' and $type eq 'array') # and !($type eq 'integer' and $value % 1 == 0)) - if (!$self->jsMatchType($type, $value)) - { - $addError->($self->jsGuessType($value)." value found, but a $type is required"); - return @E; - } if (ref $type eq 'ARRAY') { my @unionErrors; TYPE: foreach my $t (@$type) { - @unionErrors = @{ $self->checkType($t, $value, $path, $_changing, $schema) }; + @unionErrors = $self->checkType($t, $value, $path, $_changing, $schema); last unless @unionErrors; } return @unionErrors if @unionErrors; @@ -138,6 +133,11 @@ local $self->{errors} = []; $self->checkProp($value, $type, $path, undef, $_changing); return @{ $self->{errors} }; + } + elsif (!$self->jsMatchType($type, $value)) + { + $addError->($self->jsGuessType($value)." value found, but a $type is required"); + return @E; } } return; @@ -494,6 +494,7 @@ if (lc $type eq 'boolean') { + return FALSE if ref $value eq 'JSON::Schema::Null'; return TRUE if (ref $value eq 'SCALAR' and $$value==0 || $$value==1); return TRUE if ($value eq TRUE); return TRUE if ($value eq FALSE);
The subtest in this test is lacking a done_testing or a plan so its not a a valid subtest - this only was noticed on *one* of the several systems I was working with, so go figure.
Subject: 02integer.t.patch
--- /home/dihnen/.cpanm/work/1346349638.15073/JSON-Schema-0.012/t/02integer.t 2011-11-24 04:19:02.000000000 -0500 +++ JSON-Schema-0.012-manta/t/02integer.t 2012-10-10 16:16:32.000000000 -0400 @@ -40,6 +40,8 @@ $result = $schema->validate($data); ok !$result, 'too big' or map { diag "reason: $_" } $result->errors; + + done_testing; }; done_testing;
Thanks for the patches, I'll try to address this in the next few days.
Just uploaded JSON-Schema-0.013 to CPAN incorporating these patches.