lib/json-schema/validator.rb in json-schema-0.1.5 vs lib/json-schema/validator.rb in json-schema-0.1.6
- old
+ new
@@ -3,22 +3,25 @@
require 'pathname'
require 'bigdecimal'
module JSON
- class ValidationError < Exception
- attr_reader :fragments, :schema
-
- def initialize(message, fragments, schema)
- @fragments = fragments
- @schema = schema
- super(message)
- end
- end
-
- class Validator
+ class ValidationError < Exception
+ attr_reader :fragments, :schema
+ def initialize(message, fragments, schema)
+ @fragments = fragments
+ @schema = schema
+ super(message)
+ end
+ end
+
+ class Validator
+
+ @@schemas = {}
+ @@cache_schemas = false
+
ValidationMethods = [
"type",
"disallow",
"minimum",
"maximum",
@@ -40,35 +43,42 @@
"$ref"
]
def initialize(schema_data, data)
- @schemas = {}
@base_schema = initialize_schema(schema_data)
@data = initialize_data(data)
- @schemas[@base_schema.uri.to_s] = @base_schema
+ Validator.add_schema(@base_schema)
build_schemas(@base_schema)
end
# Run a simple true/false validation of data against a schema
def validate()
begin
validate_schema(@base_schema, @data, [])
+ Validator.clear_cache
return true
rescue ValidationError
+ Validator.clear_cache
return false
end
end
# Validate data against a schema, returning nil if the data is valid. If the data is invalid,
# a ValidationError will be raised with links to the specific location that the first error
# occurred during validation
def validate2()
- validate_schema(@base_schema, @data, [])
+ begin
+ validate_schema(@base_schema, @data, [])
+ Validator.clear_cache
+ rescue ValidationError
+ Validator.clear_cache
+ raise $!
+ end
nil
end
# Validate the current schema
@@ -451,11 +461,11 @@
end
temp_uri.fragment = "" if temp_uri.fragment.nil?
# Grab the parent schema from the schema list
schema_key = temp_uri.to_s.split("#")[0]
- ref_schema = @schemas[schema_key]
+ ref_schema = Validator.schemas[schema_key]
if ref_schema
# Perform fragment resolution to retrieve the appropriate level for the schema
target_schema = ref_schema.schema
fragments = temp_uri.fragment.split("/")
@@ -493,14 +503,14 @@
uri.path = (Pathname.new(parent_schema.uri.path).parent + path).cleanpath
end
uri.fragment = nil
end
- if @schemas[uri.to_s].nil?
+ if Validator.schemas[uri.to_s].nil?
begin
schema = JSON::Schema.new(JSON.parse(open(uri.to_s).read), uri)
- @schemas[uri.to_s] = schema
+ Validator.add_schema(schema)
build_schemas(schema)
rescue JSON::ParserError
# Don't rescue this error, we want JSON formatting issues to bubble up
raise $!
rescue
@@ -511,133 +521,64 @@
end
# Build all schemas with IDs, mapping out the namespace
def build_schemas(parent_schema)
- if parent_schema.schema["type"] && parent_schema.schema["type"].is_a?(Array) # If we're dealing with a Union type, there might be schemas a-brewin'
- parent_schema.schema["type"].each_with_index do |type,i|
- if type.is_a?(Hash)
- if type['$ref']
- load_ref_schema(parent_schema, type['$ref'])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(type,schema_uri)
- if type['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
- end
- end
- end
- end
- if parent_schema.schema["disallow"] && parent_schema.schema["disallow"].is_a?(Array) # If we're dealing with a Union type, there might be schemas a-brewin'
- parent_schema.schema["disallow"].each_with_index do |type,i|
- if type.is_a?(Hash)
- if type['$ref']
- load_ref_schema(parent_schema, type['$ref'])
- else
- type['id']
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(type,schema_uri)
- if type['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
+ # Check for schemas in union types
+ ["type", "disallow"].each do |key|
+ if parent_schema.schema[key] && parent_schema.schema[key].is_a?(Array)
+ parent_schema.schema[key].each_with_index do |type,i|
+ if type.is_a?(Hash)
+ handle_schema(parent_schema, type)
end
end
end
end
+ # All properties are schemas
if parent_schema.schema["properties"]
parent_schema.schema["properties"].each do |k,v|
- if v['$ref']
- load_ref_schema(parent_schema, v['$ref'])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(v,schema_uri)
- if v['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
- end
+ handle_schema(parent_schema, v)
end
end
- if parent_schema.schema["additionalProperties"].is_a?(Hash)
- if parent_schema.schema["additionalProperties"]["$ref"]
- load_ref_schema(parent_schema, parent_schema.schema["additionalProperties"]["$ref"])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(parent_schema.schema["additionalProperties"],schema_uri)
- if parent_schema.schema["additionalProperties"]['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
- end
- end
-
+ # Items are always schemas
if parent_schema.schema["items"]
items = parent_schema.schema["items"].clone
single = false
if !items.is_a?(Array)
items = [items]
single = true
end
items.each_with_index do |item,i|
- if item['$ref']
- load_ref_schema(parent_schema, item['$ref'])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(item,schema_uri)
- if item['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
- end
+ handle_schema(parent_schema, item)
end
end
- if parent_schema.schema["additionalItems"].is_a?(Hash)
- if parent_schema.schema["additionalItems"]['$ref']
- load_ref_schema(parent_schema, parent_schema.schema["additionalItems"]['$ref'])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(parent_schema.schema["additionalItems"],schema_uri)
- if parent_schema.schema["additionalItems"]['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
+ # Each of these might be schemas
+ ["additionalProperties", "additionalItems", "dependencies", "extends"].each do |key|
+ if parent_schema.schema[key].is_a?(Hash)
+ handle_schema(parent_schema, parent_schema.schema[key])
end
end
- if parent_schema.schema["dependencies"].is_a?(Hash)
- if parent_schema.schema["dependencies"]["$ref"]
- load_ref_schema(parent_schema, parent_schema.schema["dependencies"]['$ref'])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(parent_schema.schema["dependencies"],schema_uri)
- if parent_schema.schema["dependencies"]['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
- end
- end
-
- if parent_schema.schema["extends"].is_a?(Hash)
- if parent_schema.schema["extends"]['$ref']
- load_ref_schema(parent_schema, parent_schema.schema["extends"]['$ref'])
- else
- schema_uri = parent_schema.uri.clone
- schema = JSON::Schema.new(parent_schema.schema["extends"],schema_uri)
- if parent_schema.schema["extends"]['id']
- @schemas[schema.uri.to_s] = schema
- end
- build_schemas(schema)
- end
- end
end
+
+ # Either load a reference schema or create a new schema
+ def handle_schema(parent_schema, obj)
+ if obj['$ref']
+ load_ref_schema(parent_schema, obj['$ref'])
+ else
+ schema_uri = parent_schema.uri.clone
+ schema = JSON::Schema.new(obj,schema_uri)
+ if obj['id']
+ Validator.add_schema(schema)
+ end
+ build_schemas(schema)
+ end
+ end
class << self
def validate(schema, data)
validator = JSON::Validator.new(schema, data)
@@ -646,9 +587,26 @@
def validate2(schema, data)
validator = JSON::Validator.new(schema, data)
validator.validate2
end
+
+ def clear_cache
+ @@schemas = {} if @@cache_schemas == false
+ end
+
+ def schemas
+ @@schemas
+ end
+
+ def add_schema(schema)
+ @@schemas[schema.uri.to_s] = schema if @@schemas[schema.uri.to_s].nil?
+ end
+
+ def cache_schemas=(val)
+ @@cache_schemas = val == true ? true : false
+ end
+
end
private
\ No newline at end of file