Skip to content

Commit ef98622

Browse files
unevaluated* now checks adjacent keywords not just for annotations, but existence
see json-schema-org/json-schema-spec#1172 and #collaborators thread
1 parent 2da02c2 commit ef98622

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

lib/JSON/Schema/Modern/Vocabulary/Unevaluated.pm

+17-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ sub _eval_keyword_unevaluatedItems ($self, $data, $schema, $state) {
5050

5151
return 1 if not is_type('array', $data);
5252

53+
# local applicator keywords count as "evaluated"
54+
return 1 if exists $schema->{ $state->{spec_version} =~ /^draft(?:7|2019-09)$/ ? 'additionalItems' : 'items' };
55+
return 1 if $state->{spec_version} !~ /^draft(?:7|2019-09)$/ and exists $schema->{contains};
56+
5357
my @annotations = local_annotations($state);
5458

5559
# a relevant keyword already produced a 'true' annotation at this location
@@ -61,11 +65,14 @@ sub _eval_keyword_unevaluatedItems ($self, $data, $schema, $state) {
6165
if any { $bools{$_->keyword} && is_type('boolean', $_->annotation) && $_->annotation }
6266
@annotations;
6367

64-
# otherwise, evaluate at every instance item greater than the max of all 'prefixItems'/numeric
65-
# 'items' annotations that isn't in a 'contains' annotation
68+
# otherwise, evaluate at every instance item greater than the max of all 'prefixItems'
69+
# or numeric 'items' annotations
6670
my $max_index_annotation_keyword = $state->{spec_version} eq 'draft2019-09' ? 'items' : 'prefixItems';
67-
my $last_index = max(-1, grep is_type('integer', $_),
68-
map +($_->keyword eq $max_index_annotation_keyword ? $_->annotation : ()), @annotations);
71+
my $last_index = max(-1,
72+
(grep is_type('integer', $_),
73+
map +($_->keyword eq $max_index_annotation_keyword ? $_->annotation : ()), @annotations),
74+
($schema->{$max_index_annotation_keyword}//[])->$#*,
75+
);
6976

7077
return 1 if $last_index == $data->$#*;
7178

@@ -120,6 +127,8 @@ sub _eval_keyword_unevaluatedProperties ($self, $data, $schema, $state) {
120127

121128
return 1 if not is_type('object', $data);
122129

130+
return 1 if exists $schema->{additionalProperties};
131+
123132
my @evaluated_properties = map {
124133
my $keyword = $_->keyword;
125134
(grep $keyword eq $_, qw(properties additionalProperties patternProperties unevaluatedProperties))
@@ -130,6 +139,10 @@ sub _eval_keyword_unevaluatedProperties ($self, $data, $schema, $state) {
130139
my @orig_annotations = $state->{annotations}->@*;
131140
my (@valid_properties, @new_annotations);
132141
foreach my $property (sort keys %$data) {
142+
next if exists(($schema->{properties}//{})->{$property})
143+
or any { $property =~ m/$_/ } keys(($schema->{patternProperties}//{})->%*)
144+
or exists $schema->{additionalProperties};
145+
133146
next if any { $_ eq $property } @evaluated_properties;
134147

135148
if (is_type('boolean', $schema->{unevaluatedProperties})) {

t/results/draft2020-12-acceptance.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ ref.json 43 0 0
5050
refRemote.json 17 0 0
5151
required.json 9 0 0
5252
type.json 80 0 0
53-
unevaluatedItems.json 48 0 0
53+
unevaluatedItems.json 47 0 1
5454
unevaluatedProperties.json 103 0 0
5555
uniqueItems.json 68 0 0
5656
unknownKeyword.json 3 0 0
@@ -62,4 +62,4 @@ optional/format-assertion.json 4 0 0
6262
optional/non-bmp-regex.json 12 0 0
6363
optional/refOfUnknownKeyword.json 4 0 0
6464
---------------------------------------------------------------
65-
TOTAL 1153 14 0
65+
TOTAL 1152 14 1

0 commit comments

Comments
 (0)