diff --git a/lib/json-schema/attributes/type.rb b/lib/json-schema/attributes/type.rb index e8ad4637..fd60a440 100644 --- a/lib/json-schema/attributes/type.rb +++ b/lib/json-schema/attributes/type.rb @@ -57,13 +57,13 @@ def self.validate(current_schema, data, fragments, processor, validator, options end elsif !valid if union - message = "The property '#{build_fragment(fragments)}' of type #{data.class} did not match one or more of the following types:" + message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match one or more of the following types:" types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," } message.chop! validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) validation_errors(processor).last.sub_errors = union_errors else - message = "The property '#{build_fragment(fragments)}' of type #{data.class} did not match the following type:" + message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match the following type:" types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," } message.chop! validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) @@ -86,6 +86,18 @@ def self.data_valid_for_type?(data, type) valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) { return true } Array(valid_classes).any? { |c| data.is_a?(c) } end + + # Lookup Schema type of given class instance + def self.type_of_data(data) + type, klass = TYPE_CLASS_MAPPINGS.map { |k,v| [k,v] }.sort_by { |i| + k,v = i + -Array(v).map { |klass| klass.ancestors.size }.max + }.find { |i| + k,v = i + Array(v).any? { |klass| data.kind_of?(klass) } + } + type + end end end -end \ No newline at end of file +end diff --git a/lib/json-schema/schema.rb b/lib/json-schema/schema.rb index 51f4593e..29c6f003 100644 --- a/lib/json-schema/schema.rb +++ b/lib/json-schema/schema.rb @@ -10,7 +10,7 @@ def initialize(schema,uri,parent_validator=nil) @uri = uri # If there is an ID on this schema, use it to generate the URI - if @schema['id'] + if @schema['id'] && @schema['id'].kind_of?(String) temp_uri = URI.parse(@schema['id']) if temp_uri.relative? uri = uri.merge(@schema['id']) diff --git a/test/test_schema_type_attribute.rb b/test/test_schema_type_attribute.rb new file mode 100644 index 00000000..0f612c9b --- /dev/null +++ b/test/test_schema_type_attribute.rb @@ -0,0 +1,21 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../lib/json-schema' + +class TestSchemaTypeAttribute < Test::Unit::TestCase + def test_type_of_data + assert_equal(type_of_data(String.new), 'string') + assert_equal(type_of_data(Numeric.new), 'number') + assert_equal(type_of_data(1), 'integer') + assert_equal(type_of_data(true), 'boolean') + assert_equal(type_of_data(false), 'boolean') + assert_equal(type_of_data(Hash.new), 'object') + assert_equal(type_of_data(nil), 'null') + assert_equal(type_of_data(Object.new), 'any') + end + + private + + def type_of_data(data) + JSON::Schema::TypeAttribute.type_of_data(data) + end +end