Skip to content

Commit 094362a

Browse files
committed
Consider all siblings in unevaluated keywords
This uses all adjacent (same schema) results to calculate unevaluated keys/items, whether the keywords validated successfully or not. Previously, it only considered valid results, which causes confusing errors: ```ruby schemer = JSONSchemer.schema({ 'properties' => { 'x' => { 'type' => 'integer' } }, 'unevaluatedProperties' => false }) schemer.validate({ 'x' => 'invalid' }).map { _1.fetch_values('schema_pointer', 'error') } # => # [["/properties/x", "value at `/x` is not an integer"], # ["/unevaluatedProperties", "value at `/x` does not match schema"]] ``` The overall validation result shouldn't be affected, since the only additional keywords that it considers are failed ones (meaning the entire schema fails regardless of the unevaluated keys/items). Duplicate/unhelpful error messages are reduced, though, which is the main reason for making this change. Generally, this interpretation doesn't align with my reading of the spec, but there's been a lot of [discussion][0] around it and I think it makes sense from a user experience perspective. Hopefully it will get clarified in a future draft. Closes: #157 Related: - json-schema-org/json-schema-spec#1172 - https://github.com/orgs/json-schema-org/discussions/67 - https://github.com/orgs/json-schema-org/discussions/57 - https://github.com/json-schema-org/json-schema-spec/blob/2cb7c7447f9b795c9940710bf0eda966a92c937f/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md [0]: json-schema-org/json-schema-spec#1172
1 parent 513c991 commit 094362a

File tree

4 files changed

+378
-2352
lines changed

4 files changed

+378
-2352
lines changed

lib/json_schemer/draft202012/vocab/unevaluated.rb

+10-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def validate(instance, instance_location, keyword_location, context)
1818
unevaluated_items = instance.size.times.to_set
1919

2020
context.adjacent_results.each_value do |adjacent_result|
21-
collect_unevaluated_items(adjacent_result, instance_location, unevaluated_items)
21+
collect_unevaluated_items(adjacent_result, unevaluated_items)
2222
end
2323

2424
nested = unevaluated_items.map do |index|
@@ -30,8 +30,7 @@ def validate(instance, instance_location, keyword_location, context)
3030

3131
private
3232

33-
def collect_unevaluated_items(result, instance_location, unevaluated_items)
34-
return unless result.valid && result.instance_location == instance_location
33+
def collect_unevaluated_items(result, unevaluated_items)
3534
case result.source
3635
when Applicator::PrefixItems
3736
unevaluated_items.subtract(0..result.annotation)
@@ -41,7 +40,9 @@ def collect_unevaluated_items(result, instance_location, unevaluated_items)
4140
unevaluated_items.subtract(result.annotation)
4241
end
4342
result.nested&.each do |subresult|
44-
collect_unevaluated_items(subresult, instance_location, unevaluated_items)
43+
if subresult.valid && subresult.instance_location == result.instance_location
44+
collect_unevaluated_items(subresult, unevaluated_items)
45+
end
4546
end
4647
end
4748
end
@@ -61,7 +62,7 @@ def validate(instance, instance_location, keyword_location, context)
6162
evaluated_keys = Set[]
6263

6364
context.adjacent_results.each_value do |adjacent_result|
64-
collect_evaluated_keys(adjacent_result, instance_location, evaluated_keys)
65+
collect_evaluated_keys(adjacent_result, evaluated_keys)
6566
end
6667

6768
evaluated = instance.reject do |key, _value|
@@ -77,14 +78,15 @@ def validate(instance, instance_location, keyword_location, context)
7778

7879
private
7980

80-
def collect_evaluated_keys(result, instance_location, evaluated_keys)
81-
return unless result.valid && result.instance_location == instance_location
81+
def collect_evaluated_keys(result, evaluated_keys)
8282
case result.source
8383
when Applicator::Properties, Applicator::PatternProperties, Applicator::AdditionalProperties, UnevaluatedProperties
8484
evaluated_keys.merge(result.annotation)
8585
end
8686
result.nested&.each do |subresult|
87-
collect_evaluated_keys(subresult, instance_location, evaluated_keys)
87+
if subresult.valid && subresult.instance_location == result.instance_location
88+
collect_evaluated_keys(subresult, evaluated_keys)
89+
end
8890
end
8991
end
9092
end

0 commit comments

Comments
 (0)