Skip to content

Commit

Permalink
Return errors in subschemas for allOf/anyOf/oneOf
Browse files Browse the repository at this point in the history
WIP idea for addressing #1.
  • Loading branch information
davishmcclurg committed May 15, 2018
1 parent 237cd2b commit 08b781f
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 9 deletions.
31 changes: 24 additions & 7 deletions lib/json_schemer/schema/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,27 @@ def validate(data, schema = root, pointer = '', parent_uri = nil)
yield error(data, schema, pointer, 'enum') if enum && !enum.include?(data)
yield error(data, schema, pointer, 'const') if schema.key?('const') && schema['const'] != data

yield error(data, schema, pointer, 'allOf') if all_of && !all_of.all? { |subschema| valid?(data, subschema, pointer, parent_uri) }
yield error(data, schema, pointer, 'anyOf') if any_of && !any_of.any? { |subschema| valid?(data, subschema, pointer, parent_uri) }
yield error(data, schema, pointer, 'oneOf') if one_of && !one_of.one? { |subschema| valid?(data, subschema, pointer, parent_uri) }
if all_of
subschemas = all_of.lazy.map { |subschema| validate(data, subschema, pointer, parent_uri) }
yield error(data, schema, pointer, 'allOf', subschemas) unless subschemas.all?(&:none?)
end

if any_of
subschemas = any_of.lazy.map { |subschema| validate(data, subschema, pointer, parent_uri) }
yield error(data, schema, pointer, 'anyOf', subschemas) unless subschemas.any?(&:none?)
end

if one_of
subschemas = one_of.lazy.map { |subschema| validate(data, subschema, pointer, parent_uri) }
yield error(data, schema, pointer, 'oneOf', subschemas) unless subschemas.one?(&:none?)
end

yield error(data, schema, pointer, 'not') if !not_schema.nil? && valid?(data, not_schema, pointer, parent_uri)

if if_schema && valid?(data, if_schema, pointer, parent_uri)
yield error(data, schema, pointer, 'then') if !then_schema.nil? && !valid?(data, then_schema, pointer, parent_uri)
validate(data, then_schema, pointer, parent_uri, &Proc.new) unless then_schema.nil?
elsif if_schema
yield error(data, schema, pointer, 'else') if !else_schema.nil? && !valid?(data, else_schema, pointer, parent_uri)
validate(data, else_schema, pointer, parent_uri, &Proc.new) unless else_schema.nil?
end

case type
Expand Down Expand Up @@ -137,12 +149,13 @@ def child(schema)
)
end

def error(data, schema, pointer, type)
def error(data, schema, pointer, type, subschemas = nil)
{
'data' => data,
'schema' => schema,
'pointer' => pointer,
'type' => type,
'subschemas' => subschemas
}
end

Expand Down Expand Up @@ -312,7 +325,11 @@ def validate_array(data, schema, pointer, parent_uri, &block)
yield error(data, schema, pointer, 'maxItems') if max_items && data.size > max_items
yield error(data, schema, pointer, 'minItems') if min_items && data.size < min_items
yield error(data, schema, pointer, 'uniqueItems') if unique_items && data.size != data.uniq.size
yield error(data, schema, pointer, 'contains') if !contains.nil? && data.all? { |item| !valid?(item, contains, pointer, parent_uri) }

unless contains.nil?
subschemas = data.lazy.map { |subschema| validate(subschema, contains, pointer, parent_uri) }
yield error(data, schema, pointer, 'contains', subschemas) if subschemas.all?(&:any?)
end

if items.is_a?(Array)
data.each_with_index do |item, index|
Expand Down
4 changes: 2 additions & 2 deletions test/benchmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
raise if !success || errors.any?
end

x.report("json_schem, uninitialized, #{name}, invalid") do
x.report("json_schema, uninitialized, #{name}, invalid") do
success, errors = JsonSchema.parse!(schema).tap(&:expand_references!).validate(invalid)
raise if success || errors.empty?
end
Expand All @@ -104,7 +104,7 @@
raise if !success || errors.any?
end

x.report("json_schem, initialized, #{name}, invalid") do
x.report("json_schema, initialized, #{name}, invalid") do
success, errors = initialized_json_schema.validate(invalid)
raise if success || errors.empty?
end
Expand Down
19 changes: 19 additions & 0 deletions test/json_schemer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@ def test_it_does_something_useful
assert errors.none?
end

def test_error_subschemas
schema = {
'allOf' => [
{
'type' => 'integer',
'maximum' => 1
},
{
'type' => 'integer',
'maximum' => 10
}
]
}
schema = JSONSchemer.schema(schema)
error = schema.validate(11).first
assert error.fetch('type') == 'allOf'
assert error.fetch('subschemas').flat_map(&:to_a).map { |e| e.fetch('type') }.to_a == ['maximum', 'maximum']
end

{
'draft4' => JSONSchemer::Schema::Draft4,
'draft6' => JSONSchemer::Schema::Draft6,
Expand Down

0 comments on commit 08b781f

Please sign in to comment.