Skip to content

Commit f5b90b4

Browse files
David Harshabilby91
David Harsha
authored andcommitted
Return errors for nested schemas
Another idea for fixing davishmcclurg#1.
1 parent 581b89b commit f5b90b4

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

lib/json_schemer/schema/base.rb

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,42 @@ def validate_instance(instance)
120120
yield error(instance, 'enum') if enum && !enum.include?(data)
121121
yield error(instance, 'const') if schema.key?('const') && schema['const'] != data
122122

123-
yield error(instance, 'allOf') if all_of && !all_of.all? { |subschema| valid_instance?(instance.merge(schema: subschema)) }
124-
yield error(instance, 'anyOf') if any_of && !any_of.any? { |subschema| valid_instance?(instance.merge(schema: subschema)) }
125-
yield error(instance, 'oneOf') if one_of && !one_of.one? { |subschema| valid_instance?(instance.merge(schema: subschema)) }
126-
yield error(instance, 'not') if !not_schema.nil? && valid_instance?(instance.merge(schema: not_schema))
123+
if all_of
124+
subschemas = all_of.lazy.with_index.map do |subschema, index|
125+
validate_instance(instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/allOf/#{index}"))
126+
end
127+
subschemas.each { |subschema| subschema.each(&Proc.new) } unless subschemas.all?(&:none?)
128+
end
129+
130+
if any_of
131+
subschemas = any_of.lazy.with_index.map do |subschema, index|
132+
validate_instance(instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/anyOf/#{index}"))
133+
end
134+
subschemas.each { |subschema| subschema.each(&Proc.new) } unless subschemas.any?(&:none?)
135+
end
136+
137+
if one_of
138+
subschemas = one_of.lazy.with_index.map do |subschema, index|
139+
validate_instance(instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/oneOf/#{index}"))
140+
end
141+
unless subschemas.one?(&:none?)
142+
if subschemas.all?(&:none?)
143+
yield error(instance, 'oneOf')
144+
else
145+
subschemas.each { |subschema| subschema.each(&Proc.new) }
146+
end
147+
end
148+
end
149+
150+
unless not_schema.nil?
151+
subinstance = instance.merge(schema: not_schema, schema_pointer: "#{instance.schema_pointer}/not")
152+
yield error(subinstance, 'not') if valid_instance?(subinstance)
153+
end
127154

128155
if if_schema && valid_instance?(instance.merge(schema: if_schema))
129-
yield error(instance, 'then') if !then_schema.nil? && !valid_instance?(instance.merge(schema: then_schema))
156+
validate_instance(instance.merge(schema: then_schema, schema_pointer: "#{instance.schema_pointer}/then"), &Proc.new) unless then_schema.nil?
130157
elsif if_schema
131-
yield error(instance, 'else') if !else_schema.nil? && !valid_instance?(instance.merge(schema: else_schema))
158+
validate_instance(instance.merge(schema: else_schema, schema_pointer: "#{instance.schema_pointer}/else"), &Proc.new) unless else_schema.nil?
132159
end
133160

134161
case type

test/json_schemer_test.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,55 @@ def test_it_handles_regex_anchors
439439
assert !schema.valid?('fooz')
440440
end
441441

442+
def test_it_returns_nested_errors
443+
root = {
444+
'type' => 'object',
445+
'required' => [
446+
'numberOfModules'
447+
],
448+
'properties' => {
449+
'numberOfModules' => {
450+
'allOf' => [
451+
{
452+
'not' => {
453+
'type' => 'integer',
454+
'minimum' => 38
455+
}
456+
},
457+
{
458+
'not' => {
459+
'type' => 'integer',
460+
'maximum' => 37,
461+
'minimum' => 25
462+
}
463+
},
464+
{
465+
'not' => {
466+
'type' => 'integer',
467+
'maximum' => 24,
468+
'minimum' => 12
469+
}
470+
}
471+
]
472+
}
473+
}
474+
}
475+
schema = JSONSchemer.schema(root)
476+
errors = schema.validate({ 'numberOfModules' => 32 }).to_a
477+
assert errors.first == {
478+
'data' => 32,
479+
'data_pointer' => '/numberOfModules',
480+
'schema' => {
481+
'type' => 'integer',
482+
'maximum' => 37,
483+
'minimum' => 25
484+
},
485+
'schema_pointer' => '/properties/numberOfModules/allOf/1/not',
486+
'root_schema' => root,
487+
'type' => 'not'
488+
}
489+
end
490+
442491
{
443492
'draft4' => JSONSchemer::Schema::Draft4,
444493
'draft6' => JSONSchemer::Schema::Draft6,

0 commit comments

Comments
 (0)