lib/jsonschema.rb in jsonschema-2.0.1 vs lib/jsonschema.rb in jsonschema-2.0.2
- old
+ new
@@ -1,10 +1,10 @@
# vim: fileencoding=utf-8
module JSON
class Schema
- VERSION = '2.0.1'
+ VERSION = '2.0.2'
class ValueError < Exception;end
class Undefined;end
TypesMap = {
"string" => String,
"integer" => [Integer, Fixnum],
@@ -19,14 +19,23 @@
def initialize interactive
@interactive = interactive
@refmap = {}
end
+ def keys
+ @keys ||= []
+ end
+
+ def key_path
+ keys.reject{|k| k == 'self'}.join(" > ")
+ end
+
def check_property value, schema, key, parent
if schema
+ keys.push key
# if @interactive && schema['readonly']
-# raise ValueError, "#{key} is a readonly field , it can not be changed"
+# raise ValueError, "#{key_path} is a readonly field , it can not be changed"
# end
if schema['id']
@refmap[schema['id']] = schema
end
@@ -35,11 +44,11 @@
check_property(value, schema['extends'], key, parent)
end
if value == Undefined
unless schema['optional']
- raise ValueError, "#{key}: is missing and it is not optional"
+ raise ValueError, "#{key_path}: is missing and it is not optional"
end
# default
if @interactive && !parent.include?(key) && !schema['default'].nil?
unless schema["readonly"]
@@ -59,25 +68,25 @@
begin
check_type(value, schema['disallow'], key, parent)
rescue ValueError
flag = false
end
- raise ValueError, "#{key}: disallowed value was matched" if flag
+ raise ValueError, "#{key_path}: disallowed value was matched" if flag
end
unless value.nil?
- if value.instance_of? Array
+ if value.kind_of? Array
if schema['items']
- if schema['items'].instance_of?(Array)
+ if schema['items'].kind_of?(Array)
schema['items'].each_with_index {|val, index|
check_property(undefined_check(value, index), schema['items'][index], index, value)
}
if schema.include?('additionalProperties')
additional = schema['additionalProperties']
- if additional.instance_of?(FalseClass)
+ if additional.kind_of?(FalseClass)
if schema['items'].size < value.size
- raise ValueError, "#{key}: There are more values in the array than are allowed by the items and additionalProperties restrictions."
+ raise ValueError, "#{key_path}: There are more values in the array than are allowed by the items and additionalProperties restrictions."
end
else
value.each_with_index {|val, index|
check_property(undefined_check(value, index), schema['additionalProperties'], index, value)
}
@@ -88,121 +97,122 @@
check_property(undefined_check(value, index), schema['items'], index, value)
}
end
end
if schema['minItems'] && value.size < schema['minItems']
- raise ValueError, "#{key}: There must be a minimum of #{schema['minItems']} in the array"
+ raise ValueError, "#{key_path}: There must be a minimum of #{schema['minItems']} in the array"
end
if schema['maxItems'] && value.size > schema['maxItems']
- raise ValueError, "#{key}: There must be a maximum of #{schema['maxItems']} in the array"
+ raise ValueError, "#{key_path}: There must be a maximum of #{schema['maxItems']} in the array"
end
elsif schema['properties']
check_object(value, schema['properties'], schema['additionalProperties'])
elsif schema.include?('additionalProperties')
additional = schema['additionalProperties']
- unless additional.instance_of?(TrueClass)
- if additional.instance_of?(Hash) || additional.instance_of?(FalseClass)
+ unless additional.kind_of?(TrueClass)
+ if additional.kind_of?(Hash) || additional.kind_of?(FalseClass)
properties = {}
value.each {|k, val|
- if additional.instance_of?(FalseClass)
- raise ValueError, "#{key}: Additional properties not defined by 'properties' are not allowed in field '#{k}'"
+ if additional.kind_of?(FalseClass)
+ raise ValueError, "#{key_path}: Additional properties not defined by 'properties' are not allowed in field '#{k}'"
else
check_property(val, schema['additionalProperties'], k, value)
end
}
else
- raise ValueError, "#{key}: additionalProperties schema definition for field '#{}' is not an object"
+ raise ValueError, "#{key_path}: additionalProperties schema definition for field '#{}' is not an object"
end
end
end
- if value.instance_of?(String)
+ if value.kind_of?(String)
# pattern
if schema['pattern'] && !(value =~ Regexp.new(schema['pattern']))
- raise ValueError, "#{key}: does not match the regex pattern #{schema['pattern']}"
+ raise ValueError, "#{key_path}: does not match the regex pattern #{schema['pattern']}"
end
strlen = value.split(//).size
# maxLength
if schema['maxLength'] && strlen > schema['maxLength']
- raise ValueError, "#{key}: may only be #{schema['maxLength']} characters long"
+ raise ValueError, "#{key_path}: may only be #{schema['maxLength']} characters long"
end
# minLength
if schema['minLength'] && strlen < schema['minLength']
- raise ValueError, "#{key}: must be at least #{schema['minLength']} characters long"
+ raise ValueError, "#{key_path}: must be at least #{schema['minLength']} characters long"
end
end
if value.kind_of?(Numeric)
# minimum + minimumCanEqual
if schema['minimum']
minimumCanEqual = schema.fetch('minimumCanEqual', Undefined)
if minimumCanEqual == Undefined || minimumCanEqual
if value < schema['minimum']
- raise ValueError, "#{key}: must have a minimum value of #{schema['minimum']}"
+ raise ValueError, "#{key_path}: must have a minimum value of #{schema['minimum']}"
end
else
if value <= schema['minimum']
- raise ValueError, "#{key}: must have a minimum value of #{schema['minimum']}"
+ raise ValueError, "#{key_path}: must have a minimum value of #{schema['minimum']}"
end
end
end
# maximum + maximumCanEqual
if schema['maximum']
maximumCanEqual = schema.fetch('maximumCanEqual', Undefined)
if maximumCanEqual == Undefined || maximumCanEqual
if value > schema['maximum']
- raise ValueError, "#{key}: must have a maximum value of #{schema['maximum']}"
+ raise ValueError, "#{key_path}: must have a maximum value of #{schema['maximum']}"
end
else
if value >= schema['maximum']
- raise ValueError, "#{key}: must have a maximum value of #{schema['maximum']}"
+ raise ValueError, "#{key_path}: must have a maximum value of #{schema['maximum']}"
end
end
end
# maxDecimal
if schema['maxDecimal'] && schema['maxDecimal'].kind_of?(Numeric)
if value.to_s =~ /\.\d{#{schema['maxDecimal']+1},}/
- raise ValueError, "#{key}: may only have #{schema['maxDecimal']} digits of decimal places"
+ raise ValueError, "#{key_path}: may only have #{schema['maxDecimal']} digits of decimal places"
end
end
end
# enum
if schema['enum']
unless(schema['enum'].detect{|enum| enum == value })
- raise ValueError, "#{key}: does not have a value in the enumeration #{schema['enum'].join(", ")}"
+ raise ValueError, "#{key_path}: does not have a value in the enumeration #{schema['enum'].join(", ")}"
end
end
# description
- if schema['description'] && !schema['description'].instance_of?(String)
- raise ValueError, "#{key}: The description for field '#{value}' must be a string"
+ if schema['description'] && !schema['description'].kind_of?(String)
+ raise ValueError, "#{key_path}: The description for field '#{value}' must be a string"
end
# title
- if schema['title'] && !schema['title'].instance_of?(String)
- raise ValueError, "#{key}: The title for field '#{value}' must be a string"
+ if schema['title'] && !schema['title'].kind_of?(String)
+ raise ValueError, "#{key_path}: The title for field '#{value}' must be a string"
end
# format
if schema['format']
end
end
end
+ keys.pop
end
end
def check_object value, object_type_def, additional
- if object_type_def.instance_of? Hash
- if !value.instance_of?(Hash) || value.instance_of?(Array)
+ if object_type_def.kind_of? Hash
+ if !value.kind_of?(Hash) || value.kind_of?(Array)
raise ValueError, "an object is required"
end
object_type_def.each {|key, odef|
if key.index('__') != 0
@@ -210,17 +220,17 @@
end
}
end
value.each {|key, val|
if key.index('__') != 0 && object_type_def && !object_type_def[key] && additional == false
- raise ValueError, "#{value.class} The property #{key} is not defined in the schema and the schema does not allow additional properties"
+ raise ValueError, "The property #{key_path} > #{key} is not defined in the schema and the schema does not allow additional properties"
end
requires = object_type_def && object_type_def[key] && object_type_def[key]['requires']
if requires && !value.include?(requires)
- raise ValueError, "the presence of the property #{key} requires that #{requires} also be present"
+ raise ValueError, "The presence of the property #{key_path} > #{key} requires that #{requires} also be present"
end
- if object_type_def && object_type_def.instance_of?(Hash) && !object_type_def.include?(key)
+ if object_type_def && object_type_def.kind_of?(Hash) && !object_type_def.include?(key)
check_property(val, additional, key, value)
end
if !@interactive && val && val['$schema']
check_property(val, val['$schema'], key, value)
end
@@ -228,11 +238,11 @@
end
def check_type value, type, key, parent
converted_fieldtype = convert_type(type)
if converted_fieldtype
- if converted_fieldtype.instance_of? Array
+ if converted_fieldtype.kind_of? Array
datavalid = false
converted_fieldtype.each do |t|
begin
check_type(value, t, key, parent)
datavalid = true
@@ -240,16 +250,16 @@
rescue ValueError
next
end
end
unless datavalid
- raise ValueError, "#{key}: #{value.class} value found, but a #{type} is required"
+ raise ValueError, "#{key_path}: #{value.class} value found, but a #{type} is required"
end
- elsif converted_fieldtype.instance_of? Hash
+ elsif converted_fieldtype.kind_of? Hash
check_property(value, type, key, parent)
else
- unless value.instance_of? converted_fieldtype
- raise ValueError, "#{key}: #{value.class} value found, but a #{type} is required"
+ unless value.kind_of? converted_fieldtype
+ raise ValueError, "#{key_path}: #{value.class} value found, but a #{type} is required"
end
end
end
end