diff --git a/lib/json-schema/attribute.rb b/lib/json-schema/attribute.rb index a5fff92a..b462d894 100644 --- a/lib/json-schema/attribute.rb +++ b/lib/json-schema/attribute.rb @@ -10,8 +10,8 @@ def self.build_fragment(fragments) "#/#{fragments.join('/')}" end - def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors) - error = ValidationError.new(message, fragments, failed_attribute, current_schema) + def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors, property = nil) + error = ValidationError.new(message, fragments, failed_attribute, current_schema, property) if record_errors processor.validation_error(error) else diff --git a/lib/json-schema/attributes/dependencies.rb b/lib/json-schema/attributes/dependencies.rb index b8ebc646..6cc698ac 100644 --- a/lib/json-schema/attributes/dependencies.rb +++ b/lib/json-schema/attributes/dependencies.rb @@ -27,7 +27,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options def self.validate_dependency(schema, data, property, value, fragments, processor, attribute, options) return if data.key?(value.to_s) message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'" - validation_error(processor, message, fragments, schema, attribute, options[:record_errors]) + validation_error(processor, message, fragments, schema, attribute, options[:record_errors], property) end def self.accept_value?(value) diff --git a/lib/json-schema/attributes/properties.rb b/lib/json-schema/attributes/properties.rb index cbb81125..26cee6d1 100644 --- a/lib/json-schema/attributes/properties.rb +++ b/lib/json-schema/attributes/properties.rb @@ -24,7 +24,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options if required?(property_schema, options) && !data.has_key?(property) message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'" - validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) + validation_error(processor, message, fragments, current_schema, self, options[:record_errors], property) end if data.has_key?(property) diff --git a/lib/json-schema/attributes/properties_optional.rb b/lib/json-schema/attributes/properties_optional.rb index 0468676c..69885439 100644 --- a/lib/json-schema/attributes/properties_optional.rb +++ b/lib/json-schema/attributes/properties_optional.rb @@ -12,7 +12,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options if !property_schema['optional'] && !data.key?(property) message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'" - validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) + validation_error(processor, message, fragments, current_schema, self, options[:record_errors], property) end if data.has_key?(property) diff --git a/lib/json-schema/attributes/required.rb b/lib/json-schema/attributes/required.rb index b40b3f77..5545d13d 100644 --- a/lib/json-schema/attributes/required.rb +++ b/lib/json-schema/attributes/required.rb @@ -19,7 +19,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options if !prop_defaults message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'" - validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) + validation_error(processor, message, fragments, current_schema, self, options[:record_errors], property) end end end diff --git a/lib/json-schema/errors/validation_error.rb b/lib/json-schema/errors/validation_error.rb index c8527dd4..a212eaf4 100644 --- a/lib/json-schema/errors/validation_error.rb +++ b/lib/json-schema/errors/validation_error.rb @@ -2,10 +2,11 @@ module JSON class Schema class ValidationError < StandardError INDENT = " " - attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message + attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message, :property - def initialize(message, fragments, failed_attribute, schema) + def initialize(message, fragments, failed_attribute, schema, property = nil) @fragments = fragments.clone + @property = property @schema = schema @sub_errors = {} @failed_attribute = failed_attribute @@ -27,7 +28,21 @@ def to_string(subschema_level = 0) end def to_hash - base = {:schema => @schema.uri, :fragment => ::JSON::Schema::Attribute.build_fragment(fragments), :message => message_with_schema, :failed_attribute => @failed_attribute.to_s.split(":").last.split("Attribute").first} + fragment_string = ::JSON::Schema::Attribute.build_fragment(fragments) + if property + property_fragments = fragments + [property] + property_fragment_string = ::JSON::Schema::Attribute.build_fragment(property_fragments) + else + property_fragment_string = fragment_string + end + + base = { + :schema => @schema.uri, + :fragment => fragment_string, + :property_fragment => property_fragment_string, + :message => message_with_schema, + :failed_attribute => @failed_attribute.to_s.split(":").last.split("Attribute").first + } if !@sub_errors.empty? base[:errors] = @sub_errors.inject({}) do |hsh, (subschema, errors)| subschema_sym = subschema.downcase.gsub(/\W+/, '_').to_sym diff --git a/test/full_validation_test.rb b/test/full_validation_test.rb index eb0fb8fe..838cc2d7 100644 --- a/test/full_validation_test.rb +++ b/test/full_validation_test.rb @@ -133,11 +133,13 @@ def test_full_validation_with_object_errors errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) - assert(errors.length == 2) - assert(errors[0][:failed_attribute] == "Required") - assert(errors[0][:fragment] == "#/") - assert(errors[1][:failed_attribute] == "TypeV4") - assert(errors[1][:fragment] == "#/c") + assert_equal errors.length, 2 + assert_equal errors[0][:failed_attribute], "Required" + assert_equal errors[0][:fragment], "#/" + assert_equal errors[0][:property_fragment], "#/b" + assert_equal errors[1][:failed_attribute], "TypeV4" + assert_equal errors[1][:fragment], "#/c" + assert_equal errors[1][:property_fragment], "#/c" end def test_full_validation_with_nested_required_properties @@ -163,8 +165,10 @@ def test_full_validation_with_nested_required_properties errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert_equal 2, errors.length assert_equal '#/x', errors[0][:fragment] + assert_equal '#/x/b', errors[0][:property_fragment] assert_equal 'Required', errors[0][:failed_attribute] assert_equal '#/x/e', errors[1][:fragment] + assert_equal '#/x/e', errors[1][:property_fragment] assert_equal 'TypeV4', errors[1][:failed_attribute] end @@ -196,8 +200,10 @@ def test_full_validation_with_nested_required_propertiesin_array errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert_equal 2, errors.length assert_equal '#/x/0', errors[0][:fragment] + assert_equal '#/x/0/b', errors[0][:property_fragment] assert_equal 'Required', errors[0][:failed_attribute] assert_equal '#/x/1/e', errors[1][:fragment] + assert_equal '#/x/1/e', errors[1][:property_fragment] assert_equal 'TypeV4', errors[1][:failed_attribute] end end