lib/json-schema/validator.rb in json-schema-0.9.5 vs lib/json-schema/validator.rb in json-schema-0.9.6
- old
+ new
@@ -4,11 +4,11 @@
require 'bigdecimal'
require 'digest/sha1'
require 'date'
module JSON
-
+
class Schema
class ValidationError < Exception
attr_reader :fragments, :schema
def initialize(message, fragments, schema)
@@ -16,47 +16,47 @@
@schema = schema
message = "#{message} in schema #{schema.uri}"
super(message)
end
end
-
+
class SchemaError < Exception
end
-
+
class JsonParseError < Exception
end
-
+
class Attribute
def self.validate(current_schema, data, fragments, validator, options = {})
end
-
+
def self.build_fragment(fragments)
"#/#{fragments.join('/')}"
end
end
-
+
class Validator
attr_accessor :attributes, :uri
-
+
def initialize()
@attributes = {}
@uri = nil
end
-
+
def extend_schema_definition(schema_uri)
u = URI.parse(schema_uri)
validator = JSON::Validator.validators["#{u.scheme}://#{u.host}#{u.path}"]
if validator.nil?
raise SchemaError.new("Schema not found: #{u.scheme}://#{u.host}#{u.path}")
end
@attributes.merge!(validator.attributes)
end
-
+
def to_s
"#{@uri.scheme}://#{uri.host}#{uri.path}"
end
-
+
def validate(current_schema, data, fragments)
current_schema.schema.each do |attr_name,attribute|
if @attributes.has_key?(attr_name.to_s)
@attributes[attr_name.to_s].validate(current_schema, data, fragments, self)
@@ -64,12 +64,12 @@
end
data
end
end
end
-
+
class Validator
@@schemas = {}
@@cache_schemas = false
@@default_opts = {
@@ -78,11 +78,11 @@
}
@@validators = {}
@@default_validator = nil
@@available_json_backends = []
@@json_backend = nil
-
+
def initialize(schema_data, data, opts={})
@options = @@default_opts.clone.merge(opts)
# I'm not a fan of this, but it's quick and dirty to get it working for now
if @options[:version]
@@ -99,15 +99,15 @@
u = URI.parse("http://json-schema.org/#{@options[:version]}/schema#")
validator = JSON::Validator.validators["#{u.scheme}://#{u.host}#{u.path}"]
@options[:version] = validator
end
@base_schema = initialize_schema(schema_data)
- @data = initialize_data(data)
+ @data = initialize_data(data)
build_schemas(@base_schema)
- end
-
-
+ end
+
+
# Run a simple true/false validation of data against a schema
def validate()
begin
@base_schema.validate(@data,[])
Validator.clear_cache
@@ -115,32 +115,32 @@
Validator.clear_cache
raise $!
end
end
-
+
def load_ref_schema(parent_schema,ref)
uri = URI.parse(ref)
if uri.relative?
uri = parent_schema.uri.clone
-
+
# Check for absolute path
path = ref.split("#")[0]
-
+
# This is a self reference and thus the schema does not need to be re-loaded
if path.nil? || path == ''
return
end
-
+
if path && path[0,1] == '/'
uri.path = Pathname.new(path).cleanpath.to_s
else
uri = parent_schema.uri.merge(path)
end
uri.fragment = ''
end
-
+
if Validator.schemas[uri.to_s].nil?
begin
schema = JSON::Schema.new(JSON::Validator.parse(open(uri.to_s).read), uri, @options[:version])
Validator.add_schema(schema)
build_schemas(schema)
@@ -151,37 +151,37 @@
# Failures will occur when this URI cannot be referenced yet. Don't worry about it,
# the proper error will fall out if the ref isn't ever defined
end
end
end
-
-
+
+
# Build all schemas with IDs, mapping out the namespace
- def build_schemas(parent_schema)
+ def build_schemas(parent_schema)
# Build ref schemas if they exist
if parent_schema.schema["$ref"]
load_ref_schema(parent_schema, parent_schema.schema["$ref"])
end
-
+
# 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)
+ 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|
handle_schema(parent_schema, v)
end
end
-
+
# Items are always schemas
if parent_schema.schema["items"]
items = parent_schema.schema["items"].clone
single = false
if !items.is_a?(Array)
@@ -190,94 +190,94 @@
end
items.each_with_index do |item,i|
handle_schema(parent_schema, item)
end
end
-
+
# Each of these might be schemas
["additionalProperties", "additionalItems", "dependencies", "extends"].each do |key|
- if parent_schema.schema[key].is_a?(Hash)
+ if parent_schema.schema[key].is_a?(Hash)
handle_schema(parent_schema, parent_schema.schema[key])
end
end
-
+
end
-
+
# Either load a reference schema or create a new schema
def handle_schema(parent_schema, obj)
schema_uri = parent_schema.uri.clone
schema = JSON::Schema.new(obj,schema_uri,@options[:version])
if obj['id']
Validator.add_schema(schema)
end
build_schemas(schema)
end
-
-
+
+
class << self
def validate(schema, data,opts={})
begin
validator = JSON::Validator.new(schema, data, opts)
validator.validate
return true
rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError
return false
end
end
-
+
def validate!(schema, data,opts={})
validator = JSON::Validator.new(schema, data, opts)
validator.validate
return true
end
alias_method 'validate2', 'validate!'
-
+
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
-
+
def validators
@@validators
end
-
+
def default_validator
@@default_validator
end
-
+
def register_validator(v)
@@validators[v.to_s] = v
end
-
+
def register_default_validator(v)
@@default_validator = v
end
-
+
def json_backend
@@json_backend
end
-
+
def json_backend=(backend)
backend = backend.to_s
if @@available_json_backends.include?(backend)
@@json_backend = backend
else
raise JSON::Schema::JsonParseError.new("The JSON backend '#{backend}' could not be found.")
end
end
-
+
def parse(s)
case @@json_backend.to_s
when 'json'
JSON.parse(s)
when 'yajl'
@@ -287,27 +287,41 @@
else
raise JSON::Schema::JsonParseError.new("No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json")
end
end
end
-
- if Gem.available?('json')
+
+
+ if begin
+ Gem::Specification::find_by_name('json')
+ rescue
+ Gem.available?('json')
+ end
require 'json'
@@available_json_backends << 'json'
@@json_backend = 'json'
end
-
- if Gem.available?('yajl-ruby')
+
+
+ if begin
+ Gem::Specification::find_by_name('yajl-ruby')
+ rescue
+ Gem.available?('yajl-ruby')
+ end
require 'yajl'
@@available_json_backends << 'yajl'
@@json_backend = 'yajl'
end
-
-
+
+
private
- if Gem.available?('uuidtools')
+ if begin
+ Gem::Specification::find_by_name('uuidtools')
+ rescue
+ Gem.available?('uuidtools')
+ end
require 'uuidtools'
@@fake_uri_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
else
require 'uri/uuid'
@@fake_uri_generator = lambda{|s| SimpleUUID::UUID.create_v5(s,SimpleUUID::UUID::Nil).to_s }
@@ -357,16 +371,16 @@
schema_uri = URI.parse(fake_uri(schema.inspect))
schema = JSON::Schema.new(schema,schema_uri,@options[:version])
Validator.add_schema(schema)
else
raise "Invalid schema - must be either a string or a hash"
- end
-
+ end
+
schema
end
-
-
+
+
def initialize_data(data)
# Parse the data, if any
if data.is_a?(String)
begin
data = JSON::Validator.parse(data)
@@ -382,8 +396,8 @@
data = JSON::Validator.parse(open(json_uri.to_s).read)
end
end
data
end
-
+
end
end