Skip to content

Commit

Permalink
Wedge JSON::Schema::Loader into place in Validator
Browse files Browse the repository at this point in the history
Conflicts:
	lib/json-schema/validator.rb
  • Loading branch information
pd committed Nov 28, 2014
1 parent 5e77fc9 commit 088ad81
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 37 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
12 changes: 6 additions & 6 deletions lib/json-schema/attributes/ref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module JSON
class Schema
class RefAttribute < Attribute
def self.validate(current_schema, data, fragments, processor, validator, options = {})
uri,schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator)
uri, schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator)

if schema
schema.validate(data, fragments, processor, options)
Expand All @@ -18,22 +18,22 @@ def self.validate(current_schema, data, fragments, processor, validator, options
end
end

def self.get_referenced_uri_and_schema(s, current_schema, validator)
uri,schema = nil,nil
def self.get_referenced_uri_and_schema(contents, current_schema, validator)
uri, schema = nil,nil

temp_uri = Addressable::URI.parse(s['$ref'])
temp_uri = Addressable::URI.parse(contents['$ref'])
if temp_uri.relative?
temp_uri = current_schema.uri.clone
# Check for absolute path
path = s['$ref'].split("#")[0]
path = contents['$ref'].split("#")[0]
if path.nil? || path == ''
temp_uri.path = current_schema.uri.path
elsif path[0,1] == "/"
temp_uri.path = Pathname.new(path).cleanpath.to_s
else
temp_uri = current_schema.uri.join(path)
end
temp_uri.fragment = s['$ref'].split("#")[1]
temp_uri.fragment = contents['$ref'].split("#")[1]
end
temp_uri.fragment = "" if temp_uri.fragment.nil?

Expand Down
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
2 changes: 1 addition & 1 deletion lib/json-schema/schema/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def read_uri(uri)

def read_file(pathname)
if accept_file?(pathname)
pathname.read
File.read(Addressable::URI.unescape(pathname.to_s))
else
raise JSON::Schema::LoadRefused.new(pathname.to_s, :file)
end
Expand Down
58 changes: 29 additions & 29 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 @@ -99,10 +101,12 @@ def schema_from_fragment(base_schema, fragment)
raise JSON::Schema::SchemaError.new("Invalid schema encountered when resolving :fragment option")
end
end
if @options[:list] #check if the schema is validating a list
base_schema.schema = schema_to_list(base_schema.schema)

if @options[:list]
base_schema.to_array_schema
else
base_schema
end
base_schema
end

# Run a simple true/false validation of data against a schema
Expand All @@ -127,8 +131,7 @@ def load_ref_schema(parent_schema, ref)

return true if self.class.schema_loaded?(schema_uri)

schema_data = self.class.parse(custom_open(schema_uri))
schema = JSON::Schema.new(schema_data, schema_uri, @options[:version])
schema = @options[:schema_loader].load(schema_uri)
self.class.add_schema(schema)
build_schemas(schema)
end
Expand Down Expand Up @@ -218,7 +221,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 @@ -289,6 +292,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 @@ -491,55 +502,45 @@ 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 !self.class.schema_loaded?(schema_uri)
schema = JSON::Validator.parse(custom_open(schema_uri))
schema = @options[:schema_loader].load(schema_uri)
schema = JSON::Schema.stringify(schema)

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 = self.class.schema_for_uri(schema_uri)
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)
if @options[:list] && @options[:fragment].nil?
schema = schema_to_list(schema)
end
schema_uri = Addressable::URI.parse(fake_uuid(serialize(schema)))
schema = JSON::Schema.stringify(schema)
schema = JSON::Schema.new(schema,schema_uri,@options[:version])
schema = JSON::Schema.new(schema, schema_uri, @options[:version])
if @options[:list] && @options[:fragment].nil?
schema = schema.to_array_schema
end
Validator.add_schema(schema)
else
raise "Invalid schema - must be either a string or a hash"
Expand All @@ -548,7 +549,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 088ad81

Please sign in to comment.