Skip to content

Commit

Permalink
Wedge JSON::Schema::Loader into place in Validator
Browse files Browse the repository at this point in the history
  • Loading branch information
pd committed Nov 4, 2014
1 parent c123bb2 commit 7bc7362
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 27 deletions.
1 change: 0 additions & 1 deletion json-schema.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ Gem::Specification.new do |s|
s.license = "MIT"
s.required_rubygems_version = ">= 1.8"

s.add_runtime_dependency "addressable"
s.add_development_dependency "webmock"
s.add_runtime_dependency "addressable", '~> 2.3'
end
7 changes: 7 additions & 0 deletions lib/json-schema/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ def base_uri
parts.join('/') + '/'
end

# @return [JSON::Schema] a new schema matching an array whose items all match this schema.
def to_array_schema
array_schema = { 'type' => 'array', 'items' => schema }
array_schema['$schema'] = schema['$schema'] unless schema['$schema'].nil?
JSON::Schema.new(array_schema, uri, validator)
end

def to_s
@schema.to_json
end
Expand Down
52 changes: 26 additions & 26 deletions lib/json-schema/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require 'thread'
require 'yaml'

require 'json-schema/schema/loader'
require 'json-schema/errors/schema_error'
require 'json-schema/errors/json_parse_error'

Expand Down Expand Up @@ -39,6 +40,7 @@ def initialize(schema_data, data, opts={})

validator = JSON::Validator.validator_for_name(@options[:version])
@options[:version] = validator
@options[:schema_loader] ||= JSON::Validator.schema_loader

@validation_options = @options[:record_errors] ? {:record_errors => true} : {}
@validation_options[:insert_defaults] = true if @options[:insert_defaults]
Expand Down Expand Up @@ -100,9 +102,10 @@ def schema_from_fragment(base_schema, fragment)
end
end
if @options[:list] #check if the schema is validating a list
base_schema.schema = schema_to_list(base_schema.schema)
base_schema.to_array_schema
else
base_schema
end
base_schema
end

# Run a simple true/false validation of data against a schema
Expand Down Expand Up @@ -145,7 +148,7 @@ def load_ref_schema(parent_schema,ref)
end

if Validator.schemas[uri.to_s].nil?
schema = JSON::Schema.new(JSON::Validator.parse(open(uri.to_s.chomp('#')).read), uri, @options[:version])
schema = @options[:schema_loader].load(uri)
Validator.add_schema(schema)
build_schemas(schema)
end
Expand Down Expand Up @@ -238,7 +241,7 @@ def build_schemas(parent_schema)
def handle_schema(parent_schema, obj)
if obj.is_a?(Hash)
schema_uri = parent_schema.uri.clone
schema = JSON::Schema.new(obj,schema_uri,parent_schema.validator)
schema = JSON::Schema.new(obj, schema_uri, parent_schema.validator)
if obj['id']
Validator.add_schema(schema)
end
Expand Down Expand Up @@ -309,6 +312,14 @@ def fully_validate_uri(schema, data, opts={})
fully_validate(schema, data, opts.merge(:uri => true))
end

def schema_loader
@@schema_loader ||= JSON::Schema::Loader.new
end

def schema_loader=(loader)
@@schema_loader = loader
end

def clear_cache
@@schemas = {} if @@cache_schemas == false
end
Expand Down Expand Up @@ -503,53 +514,43 @@ def fake_uuid schema
@@fake_uuid_generator.call(schema)
end

def schema_to_list(schema)
new_schema = {"type" => "array", "items" => schema}
if !schema["$schema"].nil?
new_schema["$schema"] = schema["$schema"]
end

new_schema
end

def initialize_schema(schema)
if schema.is_a?(String)
begin
# Build a fake URI for this
schema_uri = Addressable::URI.parse(fake_uuid(schema))
schema = JSON::Validator.parse(schema)
schema = JSON::Schema.new(JSON::Validator.parse(schema), schema_uri, @options[:version])
if @options[:list] && @options[:fragment].nil?
schema = schema_to_list(schema)
schema = schema.to_array_schema
end
schema = JSON::Schema.new(schema,schema_uri,@options[:version])
Validator.add_schema(schema)
rescue
# Build a uri for it
schema_uri = normalized_uri(schema)
if Validator.schemas[schema_uri.to_s].nil?
schema = JSON::Validator.parse(open(schema_uri.to_s).read)
schema = @options[:schema_loader].load(schema_uri)

if @options[:list] && @options[:fragment].nil?
schema = schema_to_list(schema)
schema = schema.to_array_schema
end
schema = JSON::Schema.new(schema,schema_uri,@options[:version])

Validator.add_schema(schema)
else
schema = Validator.schemas[schema_uri.to_s]
if @options[:list] && @options[:fragment].nil?
schema = schema_to_list(schema.schema)
schema_uri = Addressable::URI.parse(fake_uuid(serialize(schema)))
schema = JSON::Schema.new(schema, schema_uri, @options[:version])
schema = schema.to_array_schema
schema.uri = Addressable::URI.parse(fake_uuid(serialize(schema.schema)))
Validator.add_schema(schema)
end
schema
end
end
elsif schema.is_a?(Hash)
schema_uri = Addressable::URI.parse(fake_uuid(serialize(schema)))
schema = JSON::Schema.new(schema, schema_uri, @options[:version])
if @options[:list] && @options[:fragment].nil?
schema = schema_to_list(schema)
schema = schema.to_array_schema
end
schema_uri = Addressable::URI.parse(fake_uuid(serialize(schema)))
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"
Expand All @@ -558,7 +559,6 @@ def initialize_schema(schema)
schema
end


def initialize_data(data)
if @options[:json]
data = JSON::Validator.parse(data)
Expand Down
50 changes: 50 additions & 0 deletions test/test_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require File.expand_path('../test_helper', __FILE__)

class TestValidator < Minitest::Test

class MockLoader
def load(location)
schema = {
'$schema' => 'http://json-schema.org/draft-04/schema#',
'type' => 'string',
'minLength' => 2
}

JSON::Schema.new(schema, Addressable::URI.parse(location.to_s))
end
end

def teardown
# Hacky. Not sure of a better tactic for resetting just yet.
JSON::Validator.send(:class_variable_set, :@@schema_loader, nil)
end

def test_default_schema_loader
loader = JSON::Validator.schema_loader
assert loader.accept_uri?(Addressable::URI.parse('http://example.com'))
assert loader.accept_file?(Pathname.new('/etc/passwd'))
end

def test_set_default_schema_loader
JSON::Validator.schema_loader = MockLoader.new

schema = { '$ref' => 'http://any.url/at/all' }
assert_valid schema, 'abc'
refute_valid schema, 'a'
end

def test_validate_with_loader
loader = MockLoader.new
schema = { '$ref' => 'http://any.url/at/all' }
assert_valid schema, 'abc', :schema_loader => loader
refute_valid schema, 'a', :schema_loader => loader
end

def test_validate_list_with_loader
loader = MockLoader.new
schema = { '$ref' => 'http://what.ever/schema' }
assert_valid schema, ['abc', 'def'], :schema_loader => loader, :list => true
refute_valid schema, ['abc', 'a'], :schema_loader => loader, :list => true
end

end

0 comments on commit 7bc7362

Please sign in to comment.