From f860cc08769bf1339b90fa2744f0f7fd28e0e43b Mon Sep 17 00:00:00 2001 From: David Harsha Date: Thu, 16 Nov 2023 10:36:39 -0800 Subject: [PATCH 1/2] 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: https://github.com/davishmcclurg/json_schemer/issues/157 Related: - https://github.com/json-schema-org/json-schema-spec/issues/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]: https://github.com/json-schema-org/json-schema-spec/issues/1172 --- .../draft202012/vocab/unevaluated.rb | 18 +- test/fixtures/draft2019-09.json | 1322 ++--------------- test/fixtures/draft2020-12.json | 1322 ++--------------- test/json_schemer_test.rb | 68 + 4 files changed, 378 insertions(+), 2352 deletions(-) diff --git a/lib/json_schemer/draft202012/vocab/unevaluated.rb b/lib/json_schemer/draft202012/vocab/unevaluated.rb index 0d866947..023b43ea 100644 --- a/lib/json_schemer/draft202012/vocab/unevaluated.rb +++ b/lib/json_schemer/draft202012/vocab/unevaluated.rb @@ -18,7 +18,7 @@ def validate(instance, instance_location, keyword_location, context) unevaluated_items = instance.size.times.to_set context.adjacent_results.each_value do |adjacent_result| - collect_unevaluated_items(adjacent_result, instance_location, unevaluated_items) + collect_unevaluated_items(adjacent_result, unevaluated_items) end nested = unevaluated_items.map do |index| @@ -30,8 +30,7 @@ def validate(instance, instance_location, keyword_location, context) private - def collect_unevaluated_items(result, instance_location, unevaluated_items) - return unless result.valid && result.instance_location == instance_location + def collect_unevaluated_items(result, unevaluated_items) case result.source when Applicator::PrefixItems unevaluated_items.subtract(0..result.annotation) @@ -41,7 +40,9 @@ def collect_unevaluated_items(result, instance_location, unevaluated_items) unevaluated_items.subtract(result.annotation) end result.nested&.each do |subresult| - collect_unevaluated_items(subresult, instance_location, unevaluated_items) + if subresult.valid && subresult.instance_location == result.instance_location + collect_unevaluated_items(subresult, unevaluated_items) + end end end end @@ -61,7 +62,7 @@ def validate(instance, instance_location, keyword_location, context) evaluated_keys = Set[] context.adjacent_results.each_value do |adjacent_result| - collect_evaluated_keys(adjacent_result, instance_location, evaluated_keys) + collect_evaluated_keys(adjacent_result, evaluated_keys) end evaluated = instance.reject do |key, _value| @@ -77,14 +78,15 @@ def validate(instance, instance_location, keyword_location, context) private - def collect_evaluated_keys(result, instance_location, evaluated_keys) - return unless result.valid && result.instance_location == instance_location + def collect_evaluated_keys(result, evaluated_keys) case result.source when Applicator::Properties, Applicator::PatternProperties, Applicator::AdditionalProperties, UnevaluatedProperties evaluated_keys.merge(result.annotation) end result.nested&.each do |subresult| - collect_evaluated_keys(subresult, instance_location, evaluated_keys) + if subresult.valid && subresult.instance_location == result.instance_location + collect_evaluated_keys(subresult, evaluated_keys) + end end end end diff --git a/test/fixtures/draft2019-09.json b/test/fixtures/draft2019-09.json index da884b6e..c26481ee 100644 --- a/test/fixtures/draft2019-09.json +++ b/test/fixtures/draft2019-09.json @@ -23317,28 +23317,6 @@ "unevaluatedProperties": false }, "type": "schema" - }, - { - "data": { - "x": { - }, - "y": { - } - }, - "data_pointer": "/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "x": { - "$ref": "#" - } - }, - "unevaluatedProperties": false - }, - "type": "schema" } ], [ @@ -23362,52 +23340,6 @@ "unevaluatedProperties": false }, "type": "schema" - }, - { - "data": { - "x": { - }, - "y": { - } - }, - "data_pointer": "/x/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "x": { - "$ref": "#" - } - }, - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": { - "x": { - "x": { - }, - "y": { - } - } - }, - "data_pointer": "/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "x": { - "$ref": "#" - } - }, - "unevaluatedProperties": false - }, - "type": "schema" } ] ], @@ -23674,108 +23606,6 @@ "y" ] } - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "y" - ], - "properties": { - "y": true - } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/b", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "y" - ], - "properties": { - "y": true - } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" } ], [ @@ -24035,7 +23865,7 @@ }, { "data": 1, - "data_pointer": "/a", + "data_pointer": "/x", "schema": false, "schema_pointer": "/unevaluatedProperties", "root_schema": { @@ -24086,7 +23916,7 @@ }, { "data": 1, - "data_pointer": "/b", + "data_pointer": "/y", "schema": false, "schema_pointer": "/unevaluatedProperties", "root_schema": { @@ -24134,155 +23964,53 @@ "unevaluatedProperties": false }, "type": "schema" - }, + } + ] + ], + [ + [ { - "data": 1, - "data_pointer": "/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "data": { + }, + "data_pointer": "", + "schema": { + "required": [ + "c" + ], + "properties": { + "c": true + } + }, + "schema_pointer": "/$defs/two/oneOf/0", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { "oneOf": [ { "$ref": "#/$defs/two" }, { "required": [ - "y" + "b" ], "properties": { - "y": true + "b": true + } + }, + { + "required": [ + "xx" + ], + "patternProperties": { + "x": true } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/y", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "y" - ], - "properties": { - "y": true - } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - } - ] - ], - [ - [ - { - "data": { - }, - "data_pointer": "", - "schema": { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - "schema_pointer": "/$defs/two/oneOf/0", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true + }, + { + "required": [ + "all" + ], + "unevaluatedProperties": true } ] }, @@ -24682,477 +24410,16 @@ { "data": { }, - "data_pointer": "", - "schema": { - "required": [ - "a" - ], - "properties": { - "a": true - } - }, - "schema_pointer": "/oneOf/1", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "required", - "details": { - "missing_keys": [ - "a" - ] - } - } - ], - [ - - ], - [ - - ], - [ - - ], - [ - - ], - [ - { - "data": { - "a": 1, - "b": 1 - }, - "data_pointer": "", - "schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "schema_pointer": "", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "oneOf" - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/b", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - } - ], - [ - { - "data": { - "a": 1, - "c": 1 - }, - "data_pointer": "", - "schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } + "data_pointer": "", + "schema": { + "required": [ + "a" ], - "unevaluatedProperties": false + "properties": { + "a": true + } }, - "schema_pointer": "", + "schema_pointer": "/oneOf/1", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -25221,14 +24488,34 @@ ], "unevaluatedProperties": false }, - "type": "oneOf" - }, + "type": "required", + "details": { + "missing_keys": [ + "a" + ] + } + } + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { + "data": { + "a": 1, + "b": 1 + }, + "data_pointer": "", + "schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { "one": { @@ -25296,13 +24583,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/c", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "schema_pointer": "", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -25371,14 +24652,14 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "oneOf" } ], [ { "data": { "a": 1, - "d": 1 + "c": 1 }, "data_pointer": "", "schema": { @@ -25519,13 +24800,16 @@ "unevaluatedProperties": false }, "type": "oneOf" - }, + } + ], + [ { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { + "data": { + "a": 1, + "d": 1 + }, + "data_pointer": "", + "schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { "one": { @@ -25593,13 +24877,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/d", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "schema_pointer": "", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -25668,7 +24946,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "oneOf" } ], [ @@ -26653,181 +25931,11 @@ "data_pointer": "", "schema": { "required": [ - "all" - ], - "unevaluatedProperties": true - }, - "schema_pointer": "/$defs/one/oneOf/3", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "required", - "details": { - "missing_keys": [ - "all" - ] - } - }, - { - "data": { - "c": 1, - "d": 1 - }, - "data_pointer": "", - "schema": { - "required": [ - "a" - ], - "properties": { - "a": true - } - }, - "schema_pointer": "/oneOf/1", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "required", - "details": { - "missing_keys": [ - "a" - ] - } - }, - { - "data": 1, - "data_pointer": "/c", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "all" + ], + "unevaluatedProperties": true + }, + "schema_pointer": "/$defs/one/oneOf/3", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -26896,13 +26004,28 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "required", + "details": { + "missing_keys": [ + "all" + ] + } }, { - "data": 1, - "data_pointer": "/d", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "data": { + "c": 1, + "d": 1 + }, + "data_pointer": "", + "schema": { + "required": [ + "a" + ], + "properties": { + "a": true + } + }, + "schema_pointer": "/oneOf/1", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -26971,19 +26094,16 @@ ], "unevaluatedProperties": false }, - "type": "schema" - } - ], - [ - - ], - [ - - ], - [ + "type": "required", + "details": { + "missing_keys": [ + "a" + ] + } + }, { "data": 1, - "data_pointer": "/foo", + "data_pointer": "/c", "schema": false, "schema_pointer": "/unevaluatedProperties", "root_schema": { @@ -27055,16 +26175,13 @@ "unevaluatedProperties": false }, "type": "schema" - } - ], - [ + }, { - "data": { - "xx": 1, - "a": 1 - }, - "data_pointer": "", - "schema": { + "data": 1, + "data_pointer": "/d", + "schema": false, + "schema_pointer": "/unevaluatedProperties", + "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { "one": { @@ -27132,7 +26249,21 @@ ], "unevaluatedProperties": false }, - "schema_pointer": "", + "type": "schema" + } + ], + [ + + ], + [ + + ], + [ + { + "data": 1, + "data_pointer": "/foo", + "schema": false, + "schema_pointer": "/unevaluatedProperties", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -27201,14 +26332,17 @@ ], "unevaluatedProperties": false }, - "type": "oneOf" - }, + "type": "schema" + } + ], + [ { - "data": 1, - "data_pointer": "/xx", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { + "data": { + "xx": 1, + "a": 1 + }, + "data_pointer": "", + "schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { "one": { @@ -27276,13 +26410,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "schema_pointer": "", "root_schema": { "$schema": "https://json-schema.org/draft/2019-09/schema", "$defs": { @@ -27351,7 +26479,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "oneOf" } ], [ @@ -28549,156 +27677,6 @@ "unevaluatedProperties": false }, "type": "oneOf" - }, - { - "data": 1, - "data_pointer": "/all", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" } ] ], diff --git a/test/fixtures/draft2020-12.json b/test/fixtures/draft2020-12.json index 7ffbab6a..3dc0caea 100644 --- a/test/fixtures/draft2020-12.json +++ b/test/fixtures/draft2020-12.json @@ -23294,28 +23294,6 @@ "unevaluatedProperties": false }, "type": "schema" - }, - { - "data": { - "x": { - }, - "y": { - } - }, - "data_pointer": "/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "x": { - "$ref": "#" - } - }, - "unevaluatedProperties": false - }, - "type": "schema" } ], [ @@ -23339,52 +23317,6 @@ "unevaluatedProperties": false }, "type": "schema" - }, - { - "data": { - "x": { - }, - "y": { - } - }, - "data_pointer": "/x/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "x": { - "$ref": "#" - } - }, - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": { - "x": { - "x": { - }, - "y": { - } - } - }, - "data_pointer": "/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "x": { - "$ref": "#" - } - }, - "unevaluatedProperties": false - }, - "type": "schema" } ] ], @@ -23651,108 +23583,6 @@ "y" ] } - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "y" - ], - "properties": { - "y": true - } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/b", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "y" - ], - "properties": { - "y": true - } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" } ], [ @@ -24012,7 +23842,7 @@ }, { "data": 1, - "data_pointer": "/a", + "data_pointer": "/x", "schema": false, "schema_pointer": "/unevaluatedProperties", "root_schema": { @@ -24063,7 +23893,7 @@ }, { "data": 1, - "data_pointer": "/b", + "data_pointer": "/y", "schema": false, "schema_pointer": "/unevaluatedProperties", "root_schema": { @@ -24111,155 +23941,53 @@ "unevaluatedProperties": false }, "type": "schema" - }, + } + ] + ], + [ + [ { - "data": 1, - "data_pointer": "/x", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "data": { + }, + "data_pointer": "", + "schema": { + "required": [ + "c" + ], + "properties": { + "c": true + } + }, + "schema_pointer": "/$defs/two/oneOf/0", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { "oneOf": [ { "$ref": "#/$defs/two" }, { "required": [ - "y" + "b" ], "properties": { - "y": true + "b": true + } + }, + { + "required": [ + "xx" + ], + "patternProperties": { + "x": true } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/y", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "properties": { - "a": true - } - }, - "two": { - "required": [ - "x" - ], - "properties": { - "x": true - } - } - }, - "allOf": [ - { - "$ref": "#/$defs/one" - }, - { - "properties": { - "b": true - } - }, - { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "y" - ], - "properties": { - "y": true - } - } - ] - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - } - ] - ], - [ - [ - { - "data": { - }, - "data_pointer": "", - "schema": { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - "schema_pointer": "/$defs/two/oneOf/0", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true + }, + { + "required": [ + "all" + ], + "unevaluatedProperties": true } ] }, @@ -24659,477 +24387,16 @@ { "data": { }, - "data_pointer": "", - "schema": { - "required": [ - "a" - ], - "properties": { - "a": true - } - }, - "schema_pointer": "/oneOf/1", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "required", - "details": { - "missing_keys": [ - "a" - ] - } - } - ], - [ - - ], - [ - - ], - [ - - ], - [ - - ], - [ - { - "data": { - "a": 1, - "b": 1 - }, - "data_pointer": "", - "schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "schema_pointer": "", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "oneOf" - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/b", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - } - ], - [ - { - "data": { - "a": 1, - "c": 1 - }, - "data_pointer": "", - "schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } + "data_pointer": "", + "schema": { + "required": [ + "a" ], - "unevaluatedProperties": false + "properties": { + "a": true + } }, - "schema_pointer": "", + "schema_pointer": "/oneOf/1", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -25198,14 +24465,34 @@ ], "unevaluatedProperties": false }, - "type": "oneOf" - }, + "type": "required", + "details": { + "missing_keys": [ + "a" + ] + } + } + ], + [ + + ], + [ + + ], + [ + + ], + [ + + ], + [ { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { + "data": { + "a": 1, + "b": 1 + }, + "data_pointer": "", + "schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { "one": { @@ -25273,13 +24560,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/c", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "schema_pointer": "", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -25348,14 +24629,14 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "oneOf" } ], [ { "data": { "a": 1, - "d": 1 + "c": 1 }, "data_pointer": "", "schema": { @@ -25496,13 +24777,16 @@ "unevaluatedProperties": false }, "type": "oneOf" - }, + } + ], + [ { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { + "data": { + "a": 1, + "d": 1 + }, + "data_pointer": "", + "schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { "one": { @@ -25570,13 +24854,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/d", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "schema_pointer": "", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -25645,7 +24923,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "oneOf" } ], [ @@ -26630,181 +25908,11 @@ "data_pointer": "", "schema": { "required": [ - "all" - ], - "unevaluatedProperties": true - }, - "schema_pointer": "/$defs/one/oneOf/3", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "required", - "details": { - "missing_keys": [ - "all" - ] - } - }, - { - "data": { - "c": 1, - "d": 1 - }, - "data_pointer": "", - "schema": { - "required": [ - "a" - ], - "properties": { - "a": true - } - }, - "schema_pointer": "/oneOf/1", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "required", - "details": { - "missing_keys": [ - "a" - ] - } - }, - { - "data": 1, - "data_pointer": "/c", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "all" + ], + "unevaluatedProperties": true + }, + "schema_pointer": "/$defs/one/oneOf/3", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -26873,13 +25981,28 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "required", + "details": { + "missing_keys": [ + "all" + ] + } }, { - "data": 1, - "data_pointer": "/d", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "data": { + "c": 1, + "d": 1 + }, + "data_pointer": "", + "schema": { + "required": [ + "a" + ], + "properties": { + "a": true + } + }, + "schema_pointer": "/oneOf/1", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -26948,19 +26071,16 @@ ], "unevaluatedProperties": false }, - "type": "schema" - } - ], - [ - - ], - [ - - ], - [ + "type": "required", + "details": { + "missing_keys": [ + "a" + ] + } + }, { "data": 1, - "data_pointer": "/foo", + "data_pointer": "/c", "schema": false, "schema_pointer": "/unevaluatedProperties", "root_schema": { @@ -27032,16 +26152,13 @@ "unevaluatedProperties": false }, "type": "schema" - } - ], - [ + }, { - "data": { - "xx": 1, - "a": 1 - }, - "data_pointer": "", - "schema": { + "data": 1, + "data_pointer": "/d", + "schema": false, + "schema_pointer": "/unevaluatedProperties", + "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { "one": { @@ -27109,7 +26226,21 @@ ], "unevaluatedProperties": false }, - "schema_pointer": "", + "type": "schema" + } + ], + [ + + ], + [ + + ], + [ + { + "data": 1, + "data_pointer": "/foo", + "schema": false, + "schema_pointer": "/unevaluatedProperties", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -27178,14 +26309,17 @@ ], "unevaluatedProperties": false }, - "type": "oneOf" - }, + "type": "schema" + } + ], + [ { - "data": 1, - "data_pointer": "/xx", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { + "data": { + "xx": 1, + "a": 1 + }, + "data_pointer": "", + "schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { "one": { @@ -27253,13 +26387,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", + "schema_pointer": "", "root_schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "$defs": { @@ -27328,7 +26456,7 @@ ], "unevaluatedProperties": false }, - "type": "schema" + "type": "oneOf" } ], [ @@ -28526,156 +27654,6 @@ "unevaluatedProperties": false }, "type": "oneOf" - }, - { - "data": 1, - "data_pointer": "/all", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" - }, - { - "data": 1, - "data_pointer": "/a", - "schema": false, - "schema_pointer": "/unevaluatedProperties", - "root_schema": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "one": { - "oneOf": [ - { - "$ref": "#/$defs/two" - }, - { - "required": [ - "b" - ], - "properties": { - "b": true - } - }, - { - "required": [ - "xx" - ], - "patternProperties": { - "x": true - } - }, - { - "required": [ - "all" - ], - "unevaluatedProperties": true - } - ] - }, - "two": { - "oneOf": [ - { - "required": [ - "c" - ], - "properties": { - "c": true - } - }, - { - "required": [ - "d" - ], - "properties": { - "d": true - } - } - ] - } - }, - "oneOf": [ - { - "$ref": "#/$defs/one" - }, - { - "required": [ - "a" - ], - "properties": { - "a": true - } - } - ], - "unevaluatedProperties": false - }, - "type": "schema" } ] ], diff --git a/test/json_schemer_test.rb b/test/json_schemer_test.rb index f4fe2789..22e31cae 100644 --- a/test/json_schemer_test.rb +++ b/test/json_schemer_test.rb @@ -324,6 +324,74 @@ def test_draft7_additional_items_error assert_equal('array items at root do not match `additionalItems` schema', schemer.validate([1, 2], :resolve_enumerators => true).dig('errors', 1, 'error')) end + def test_unevaluated_items_errors + schemer = JSONSchemer.schema({ + 'prefixItems' => [ + { 'type' => 'integer' } + ], + 'unevaluatedItems' => false + }) + assert_equal(['/prefixItems/0'], schemer.validate(['invalid']).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/unevaluatedItems'], schemer.validate([1, 'unevaluated']).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/prefixItems/0', '/unevaluatedItems'], schemer.validate(['invalid', 'unevaluated']).map { |error| error.fetch('schema_pointer') }) + end + + def test_unevaluated_properties_errors + schemer = JSONSchemer.schema({ + 'properties' => { + 'foo' => { + 'type' => 'integer' + } + }, + 'unevaluatedProperties' => false + }) + assert_equal(['/properties/foo'], schemer.validate({ 'foo' => 'invalid' }).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/unevaluatedProperties'], schemer.validate({ 'bar' => 'unevaluated' }).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/unevaluatedProperties'], schemer.validate({ 'foo' => 1, 'bar' => 'unevaluated' }).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/properties/foo', '/unevaluatedProperties'], schemer.validate({ 'foo' => 'invalid', 'bar' => '?' }).map { |error| error.fetch('schema_pointer') }) + + schemer = JSONSchemer.schema({ + 'properties' => { + 'foo' => { + 'type' => 'integer' + }, + 'bar' => { + 'type' => 'string' + } + }, + 'unevaluatedProperties' => false + }) + assert_equal(['/properties/foo'], schemer.validate({ 'foo' => 'invalid', 'bar' => 'valid' }).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/properties/bar'], schemer.validate({ 'foo' => 1, 'bar' => 1 }).map { |error| error.fetch('schema_pointer') }) + end + + # https://github.com/json-schema-org/json-schema-spec/issues/1172#issuecomment-1062540587 + def test_unevaluated_properties_inconsistent_errors + all_of = [ + { + 'properties' => { + 'foo' => true + } + }, + false + ] + schemer1 = JSONSchemer.schema({ + 'allOf' => all_of, + 'unevaluatedProperties' => false + }) + schemer2 = JSONSchemer.schema({ + 'allOf' => [ + { 'allOf' => all_of } + ], + 'unevaluatedProperties' => false + }) + instance = { + 'foo' => true + } + assert_equal(['/allOf/1'], schemer1.validate(instance).map { |error| error.fetch('schema_pointer') }) + assert_equal(['/allOf/0/allOf/1', '/unevaluatedProperties'], schemer2.validate(instance).map { |error| error.fetch('schema_pointer') }) + end + def test_inspect output = JSONSchemer.openapi31_document.inspect assert_includes(output, 'JSONSchemer::Schema') From e512f7636bf61d7c56d67c61d8cbb096c03f4022 Mon Sep 17 00:00:00 2001 From: David Harsha Date: Sat, 16 Dec 2023 14:51:55 -0800 Subject: [PATCH 2/2] Add false schema errors for unevaluated keywords And change `additionalProperties` message to be consistent. --- lib/json_schemer/draft202012/vocab/applicator.rb | 2 +- lib/json_schemer/draft202012/vocab/unevaluated.rb | 8 ++++++++ test/output_format_test.rb | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/json_schemer/draft202012/vocab/applicator.rb b/lib/json_schemer/draft202012/vocab/applicator.rb index c759d7c5..e756f17b 100644 --- a/lib/json_schemer/draft202012/vocab/applicator.rb +++ b/lib/json_schemer/draft202012/vocab/applicator.rb @@ -300,7 +300,7 @@ def error(formatted_instance_location:, **) end def false_schema_error(formatted_instance_location:, **) - "object property at #{formatted_instance_location} is not defined and schema does not allow additional properties" + "object property at #{formatted_instance_location} is a disallowed additional property" end def parse diff --git a/lib/json_schemer/draft202012/vocab/unevaluated.rb b/lib/json_schemer/draft202012/vocab/unevaluated.rb index 023b43ea..a24d8681 100644 --- a/lib/json_schemer/draft202012/vocab/unevaluated.rb +++ b/lib/json_schemer/draft202012/vocab/unevaluated.rb @@ -8,6 +8,10 @@ def error(formatted_instance_location:, **) "array items at #{formatted_instance_location} do not match `unevaluatedItems` schema" end + def false_schema_error(formatted_instance_location:, **) + "array item at #{formatted_instance_location} is a disallowed unevaluated item" + end + def parse subschema(value) end @@ -52,6 +56,10 @@ def error(formatted_instance_location:, **) "object properties at #{formatted_instance_location} do not match `unevaluatedProperties` schema" end + def false_schema_error(formatted_instance_location:, **) + "object property at #{formatted_instance_location} is a disallowed unevaluated property" + end + def parse subschema(value) end diff --git a/test/output_format_test.rb b/test/output_format_test.rb index 001bb5be..6463f296 100644 --- a/test/output_format_test.rb +++ b/test/output_format_test.rb @@ -65,7 +65,7 @@ def test_output_formats_match_specification_examples 'keywordLocation' => '/items/$ref/additionalProperties', 'absoluteKeywordLocation' => 'https://example.com/polygon#/$defs/point/additionalProperties', 'instanceLocation' => '/1/z', - 'error' => 'object property at `/1/z` is not defined and schema does not allow additional properties' # 'Additional property \'z\' found but was invalid.' + 'error' => 'object property at `/1/z` is a disallowed additional property' # 'Additional property \'z\' found but was invalid.' }, { 'valid' => false, # not in spec @@ -107,7 +107,7 @@ def test_output_formats_match_specification_examples 'keywordLocation' => '/items/$ref/additionalProperties', 'absoluteKeywordLocation' => 'https://example.com/polygon#/$defs/point/additionalProperties', 'instanceLocation' => '/1/z', - 'error' => 'object property at `/1/z` is not defined and schema does not allow additional properties' # 'Additional property \'z\' found but was invalid.' + 'error' => 'object property at `/1/z` is a disallowed additional property' # 'Additional property \'z\' found but was invalid.' }, { 'valid' => false,