From cb52269d6e0f5ff64888d5f377ae2741cda32694 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 6 Mar 2015 11:58:49 +0000 Subject: [PATCH 01/43] Only rescue errors explicitly There are a lot of places in the code where we rescue any error, at all. That's quite dangerous, as it could conceal bugs. I've changed it so that we always specify which error class we want to catch. Mostly it's been a minor change, but there are two API changes: * When it comes to loading data I've had to introduce an explicit list of protocols which we can load json over (otherwise it's possible to have a uri with a scheme that makes no sense - it'd still be a valid uri but loading from it is impossible). I've used the list of protocols that addressable recognizes for now. * No matter what JSON parser you use, we now always raise a JSON::Schema::JsonParseError. Without doing this it would be tricky to handle parser errors identically, for all parsers (the other option would be to catch a long list of potential parse errors, but this seems more sensible). --- lib/json-schema/attributes/formats/date.rb | 3 +- .../attributes/formats/date_time.rb | 14 ++-- lib/json-schema/attributes/not.rb | 2 +- lib/json-schema/errors/json_load_error.rb | 6 ++ lib/json-schema/errors/schema_parse_error.rb | 8 +++ lib/json-schema/schema/reader.rb | 4 +- lib/json-schema/util/uri.rb | 2 + lib/json-schema/validator.rb | 64 ++++++++++++------- test/test_helper.rb | 10 --- test/test_initialize_data.rb | 22 ++++--- test/test_schema_loader.rb | 2 +- 11 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 lib/json-schema/errors/json_load_error.rb create mode 100644 lib/json-schema/errors/schema_parse_error.rb diff --git a/lib/json-schema/attributes/formats/date.rb b/lib/json-schema/attributes/formats/date.rb index 24b21700..451f6ff1 100644 --- a/lib/json-schema/attributes/formats/date.rb +++ b/lib/json-schema/attributes/formats/date.rb @@ -11,7 +11,8 @@ def self.validate(current_schema, data, fragments, processor, validator, options if REGEXP.match(data) begin Date.parse(data) - rescue Exception + rescue ArgumentError => e + raise e unless e.message == 'invalid date' validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end else diff --git a/lib/json-schema/attributes/formats/date_time.rb b/lib/json-schema/attributes/formats/date_time.rb index b1baa15c..01987485 100644 --- a/lib/json-schema/attributes/formats/date_time.rb +++ b/lib/json-schema/attributes/formats/date_time.rb @@ -14,18 +14,16 @@ def self.validate(current_schema, data, fragments, processor, validator, options begin Date.parse(parts[0]) - rescue Exception + rescue ArgumentError => e + raise e unless e.message == 'invalid date' validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) return end - begin - validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23 - validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59 - validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59 - rescue Exception - validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) - end + validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m.length < 4 + validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23 + validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59 + validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59 else validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end diff --git a/lib/json-schema/attributes/not.rb b/lib/json-schema/attributes/not.rb index 52729ef3..64fbd6e3 100644 --- a/lib/json-schema/attributes/not.rb +++ b/lib/json-schema/attributes/not.rb @@ -17,7 +17,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options message = "The property '#{build_fragment(fragments)}' of type #{data.class} matched the disallowed schema" failed = false end - rescue + rescue ValidationError # Yay, we failed validation. end diff --git a/lib/json-schema/errors/json_load_error.rb b/lib/json-schema/errors/json_load_error.rb new file mode 100644 index 00000000..f5a74b78 --- /dev/null +++ b/lib/json-schema/errors/json_load_error.rb @@ -0,0 +1,6 @@ +module JSON + class Schema + class JsonLoadError < StandardError + end + end +end diff --git a/lib/json-schema/errors/schema_parse_error.rb b/lib/json-schema/errors/schema_parse_error.rb new file mode 100644 index 00000000..afdf84f1 --- /dev/null +++ b/lib/json-schema/errors/schema_parse_error.rb @@ -0,0 +1,8 @@ +require 'json/common' + +module JSON + class Schema + class SchemaParseError < JSON::ParserError + end + end +end diff --git a/lib/json-schema/schema/reader.rb b/lib/json-schema/schema/reader.rb index 9b13c66b..4121bf99 100644 --- a/lib/json-schema/schema/reader.rb +++ b/lib/json-schema/schema/reader.rb @@ -57,8 +57,8 @@ def initialize(options = {}) # @param location [#to_s] The location from which to read the schema # @return [JSON::Schema] # @raise [JSON::Schema::ReadRefused] if +accept_uri+ or +accept_file+ - # indicated the schema should not be readed - # @raise [JSON::ParserError] if the schema was not a valid JSON object + # indicated the schema could not be read + # @raise [JSON::Schema::ParseError] if the schema was not a valid JSON object def read(location) uri = Addressable::URI.parse(location.to_s) body = if uri.scheme.nil? || uri.scheme == 'file' diff --git a/lib/json-schema/util/uri.rb b/lib/json-schema/util/uri.rb index eca9e6ed..951c2ce9 100644 --- a/lib/json-schema/util/uri.rb +++ b/lib/json-schema/util/uri.rb @@ -1,6 +1,8 @@ module JSON module Util module URI + SUPPORTED_PROTOCOLS = %w(http https ftp tftp sftp ssh svn+ssh telnet nntp gopher wais ldap prospero) + def self.normalized_uri(uri) uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI) # Check for absolute path diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index c20971b7..0adb1e8d 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -9,6 +9,8 @@ require 'json-schema/schema/reader' require 'json-schema/errors/schema_error' +require 'json-schema/errors/schema_parse_error' +require 'json-schema/errors/json_load_error' require 'json-schema/errors/json_parse_error' module JSON @@ -54,17 +56,13 @@ def initialize(schema_data, data, opts={}) # validate the schema, if requested if @options[:validate_schema] - begin - if @base_schema.schema["$schema"] - base_validator = JSON::Validator.validator_for_name(@base_schema.schema["$schema"]) - end - metaschema = base_validator ? base_validator.metaschema : validator.metaschema - # Don't clear the cache during metaschema validation! - meta_validator = JSON::Validator.new(metaschema, @base_schema.schema, {:clear_cache => false}) - meta_validator.validate - rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError - raise $! + if @base_schema.schema["$schema"] + base_validator = JSON::Validator.validator_for_name(@base_schema.schema["$schema"]) end + metaschema = base_validator ? base_validator.metaschema : validator.metaschema + # Don't clear the cache during metaschema validation! + meta_validator = JSON::Validator.new(metaschema, @base_schema.schema, {:clear_cache => false}) + meta_validator.validate end # If the :fragment option is set, try and validate against the fragment @@ -415,15 +413,27 @@ def json_backend=(backend) def parse(s) if defined?(MultiJson) - MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s) + begin + MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s) + rescue MultiJson::ParseError => e + raise JSON::Schema::JsonParseError.new(e.message) + end else case @@json_backend.to_s when 'json' - JSON.parse(s, :quirks_mode => true) + begin + JSON.parse(s, :quirks_mode => true) + rescue JSON::ParserError => e + raise JSON::Schema::JsonParseError.new(e.message) + end when 'yajl' - json = StringIO.new(s) - parser = Yajl::Parser.new - parser.parse(json) or raise JSON::Schema::JsonParseError.new("The JSON could not be parsed by yajl") + begin + json = StringIO.new(s) + parser = Yajl::Parser.new + parser.parse(json) or raise JSON::Schema::JsonParseError.new("The JSON could not be parsed by yajl") + rescue Yajl::ParseError => e + raise JSON::Schema::JsonParseError.new(e.message) + end else raise JSON::Schema::JsonParseError.new("No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json") end @@ -520,7 +530,7 @@ def initialize_schema(schema) schema = schema.to_array_schema end Validator.add_schema(schema) - rescue + rescue JSON::Schema::JsonParseError # Build a uri for it schema_uri = Util::URI.normalized_uri(schema) if !self.class.schema_loaded?(schema_uri) @@ -551,7 +561,7 @@ def initialize_schema(schema) end Validator.add_schema(schema) else - raise "Invalid schema - must be either a string or a hash" + raise SchemaParseError, "Invalid schema - must be either a string or a hash" end schema @@ -567,12 +577,12 @@ def initialize_data(data) elsif data.is_a?(String) begin data = JSON::Validator.parse(data) - rescue + rescue JSON::Schema::JsonParseError begin json_uri = Util::URI.normalized_uri(data) data = JSON::Validator.parse(custom_open(json_uri)) - rescue - # Silently discard the error - the data will not change + rescue JSON::Schema::JsonLoadError + # Silently discard the error - use the data as-is end end end @@ -582,10 +592,18 @@ def initialize_data(data) def custom_open(uri) uri = Util::URI.normalized_uri(uri) if uri.is_a?(String) - if uri.absolute? && uri.scheme != 'file' - open(uri.to_s).read + if uri.absolute? && Util::URI::SUPPORTED_PROTOCOLS.include?(uri.scheme) + begin + open(uri.to_s).read + rescue OpenURI::HTTPError, Timeout::Error => e + raise JSON::Schema::JsonLoadError, e.message + end else - File.read(Addressable::URI.unescape(uri.path)) + begin + File.read(Addressable::URI.unescape(uri.path)) + rescue SystemCallError => e + raise JSON::Schema::JsonLoadError, e.message + end end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index e8d6aef1..14510863 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -34,14 +34,4 @@ def refute_valid(schema, data, options = {}) errors = JSON::Validator.fully_validate(schema, data, options) refute_equal([], errors, "#{data.inspect} should be invalid for schema:\n#{schema.inspect}") end - - def parser_error - if defined?(::Yajl) - Yajl::ParseError - elsif defined?(::MultiJson) - MultiJson::ParseError - else - JSON::ParserError - end - end end diff --git a/test/test_initialize_data.rb b/test/test_initialize_data.rb index bf61c65f..77d6c112 100644 --- a/test/test_initialize_data.rb +++ b/test/test_initialize_data.rb @@ -10,11 +10,11 @@ def test_parse_character_string assert(JSON::Validator.validate(schema, data, :parse_data => false)) - assert_raises(parser_error) do + assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, :json => true) end - assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) } + assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_integer_string @@ -27,7 +27,7 @@ def test_parse_integer_string assert(JSON::Validator.validate(schema, data, :json => true)) - assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) } + assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_hash_string @@ -40,7 +40,7 @@ def test_parse_hash_string assert(JSON::Validator.validate(schema, data, :json => true)) - assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) } + assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_json_string @@ -53,7 +53,7 @@ def test_parse_json_string assert(JSON::Validator.validate(schema, data, :json => true)) - assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) } + assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_valid_uri_string @@ -66,7 +66,7 @@ def test_parse_valid_uri_string assert(JSON::Validator.validate(schema, data, :parse_data => false)) - assert_raises(parser_error) do + assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, :json => true) end @@ -83,11 +83,17 @@ def test_parse_invalid_uri_string assert(JSON::Validator.validate(schema, data, :parse_data => false)) - assert_raises(parser_error) do + stub_request(:get, "foo.bar").to_return(:status => [500, "Internal Server Error"]) + + assert(JSON::Validator.validate(schema, data)) + + assert(JSON::Validator.validate(schema, data, :parse_data => false)) + + assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, :json => true) end - assert_raises(Timeout::Error) { JSON::Validator.validate(schema, data, :uri => true) } + assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_integer diff --git a/test/test_schema_loader.rb b/test/test_schema_loader.rb index b267e071..1972c830 100644 --- a/test/test_schema_loader.rb +++ b/test/test_schema_loader.rb @@ -67,7 +67,7 @@ def test_parse_error reader = JSON::Schema::Reader.new - assert_raises(parser_error) do + assert_raises(JSON::Schema::JsonParseError) do reader.read(ADDRESS_SCHEMA_URI) end end From d16d9b1c64cb25619265c22474c7f9d8b806070e Mon Sep 17 00:00:00 2001 From: Jonas Peschla Date: Thu, 12 Mar 2015 20:35:28 +0100 Subject: [PATCH 02/43] Update test-suite --- test/test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-suite b/test/test-suite index 8f867168..9208016d 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 8f867168d17497a775141704960906db83634a04 +Subproject commit 9208016d04c1b6774d5a17e8b037161873414edb From 701a6e27b5c2be94fac3f39da8122ba8d38a2cf3 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Tue, 10 Feb 2015 08:24:52 +0000 Subject: [PATCH 03/43] Enabled warnings when running tests --- Rakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Rakefile b/Rakefile index a6a66259..55704a5b 100644 --- a/Rakefile +++ b/Rakefile @@ -14,6 +14,8 @@ end Rake::TestTask.new do |t| t.libs << "." + t.warning = true + t.verbose = true t.test_files = FileList['test/test*.rb'] end From c7dd2fcef1c0ffa85b9a21087b80512e388e27d5 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Sun, 29 Mar 2015 09:34:51 +0100 Subject: [PATCH 04/43] Excluded test_helper.rb from the test files being run --- Rakefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 55704a5b..76591dd9 100644 --- a/Rakefile +++ b/Rakefile @@ -16,7 +16,9 @@ Rake::TestTask.new do |t| t.libs << "." t.warning = true t.verbose = true - t.test_files = FileList['test/test*.rb'] + t.test_files = FileList.new('test/test*.rb') do |fl| + fl.exclude(/test_helper\.rb$/) + end end task :test => :update_common_tests From 6905dcb295a8c1f46594f3fb29914fbb20e2b034 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Sun, 29 Mar 2015 09:36:38 +0100 Subject: [PATCH 05/43] Specified addressable 2.3.8 as a dev dependency Older versions raised ruby warnings --- json-schema.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json-schema.gemspec b/json-schema.gemspec index 1cc71dd7..4c144529 100644 --- a/json-schema.gemspec +++ b/json-schema.gemspec @@ -23,5 +23,5 @@ Gem::Specification.new do |s| s.add_development_dependency "webmock" s.add_development_dependency "bundler" - s.add_runtime_dependency "addressable", '~> 2.3.7' + s.add_runtime_dependency "addressable", '~> 2.3.8' end From a71b74f7f25e8bea1f125ce45163da13a9ae372e Mon Sep 17 00:00:00 2001 From: JKGisMe Date: Fri, 10 Apr 2015 15:01:38 -0500 Subject: [PATCH 06/43] Explicitly notes :strict mode overrides any required properties set in the schema --- README.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.textile b/README.textile index d3acf465..42827d67 100644 --- a/README.textile +++ b/README.textile @@ -82,7 +82,7 @@ JSON::Validator.validate('user.json', data, :list => true) h3. Strictly validate an object's properties -With the :strict option, validation fails when an object contains properties that are not defined in the schema's property list or doesn't match the additionalProperties property. Furthermore, all properties are treated as required by default. +With the :strict option, validation fails when an object contains properties that are not defined in the schema's property list or doesn't match the additionalProperties property. Furthermore, all properties are treated as required regardless of required properties set in the schema.
 require 'rubygems'

From 710b6f25e68f68b765a4c39f6397e4b4eec95b5d Mon Sep 17 00:00:00 2001
From: Martin Konecny 
Date: Sun, 1 Nov 2015 20:57:47 -0500
Subject: [PATCH 07/43] Update README.textile

---
 README.textile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.textile b/README.textile
index 42827d67..2e1af456 100644
--- a/README.textile
+++ b/README.textile
@@ -214,7 +214,7 @@ schema = {
   "type" => "object",
   "required" => ["a"],
   "properties" => {
-    "a" => {"type" => "integer"}  # This will fail schema validation!
+    "a" => {"type" => "integer", "required" => "true"}  # This will fail schema validation!
   }
 }
 

From 21d22e4fd31d42683a535513bc36852fe29580fd Mon Sep 17 00:00:00 2001
From: James McKinney 
Date: Tue, 24 Nov 2015 03:08:24 -0500
Subject: [PATCH 08/43] Demonstrate failure to #register_format_validator on
 default_validator

---
 test/test_custom_format.rb | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/test/test_custom_format.rb b/test/test_custom_format.rb
index e7ab3cc6..a53f165a 100644
--- a/test/test_custom_format.rb
+++ b/test/test_custom_format.rb
@@ -3,7 +3,7 @@
 
 class JSONSchemaCustomFormatTest < Minitest::Test
   def setup
-    @all_versions = ['draft1', 'draft2', 'draft3', 'draft4']
+    @all_versions = ['draft1', 'draft2', 'draft3', 'draft4', nil]
     @format_proc = lambda { |value| raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" }
     @schema_4 = {
       "$schema" => "http://json-schema.org/draft-04/schema#",
@@ -20,36 +20,37 @@ def setup
     @schema_2["$schema"] = "http://json-schema.org/draft-02/schema#"
     @schema_1 = @schema_4.clone
     @schema_1["$schema"] = "http://json-schema.org/draft-01/schema#"
+    @default = @schema_4.clone
     @schemas = {
       "draft1" => @schema_1,
       "draft2" => @schema_2,
       "draft3" => @schema_3,
-      "draft4" => @schema_4
+      "draft4" => @schema_4,
     }
     JSON::Validator.restore_default_formats
   end
 
   def test_single_registration
     @all_versions.each do |version|
-      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' for #{version} should be nil")
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' for #{version || 'default'} should be nil")
       JSON::Validator.register_format_validator("custom", @format_proc, [version])
-      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version}")
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version || 'default'}")
       (@all_versions - [version]).each do |other_version|
-        assert(JSON::Validator.validator_for_name(other_version).formats['custom'].nil?, "Format 'custom' should still be nil for #{other_version}")
+        assert(JSON::Validator.validator_for_name(other_version).formats['custom'].nil?, "Format 'custom' should still be nil for #{other_version || 'default'}")
       end
       JSON::Validator.deregister_format_validator("custom", [version])
-      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' should be deregistered for #{version}")
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' should be deregistered for #{version || 'default'}")
     end
   end
 
   def test_register_for_all_by_default
     JSON::Validator.register_format_validator("custom", @format_proc)
     @all_versions.each do |version|
-      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version}")
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version || 'default'}")
     end
     JSON::Validator.restore_default_formats
     @all_versions.each do |version|
-      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' should still be nil for #{version}")
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' should still be nil for #{version || 'default'}")
     end
   end
 
@@ -57,18 +58,18 @@ def test_multi_registration
     unregistered_version = @all_versions.delete("draft1")
     JSON::Validator.register_format_validator("custom", @format_proc, @all_versions)
     @all_versions.each do |version|
-      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version}")
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version || 'default'}")
     end
     assert(JSON::Validator.validator_for_name(unregistered_version).formats['custom'].nil?, "Format 'custom' should still be nil for #{unregistered_version}")
   end
 
   def test_format_validation
-    @all_versions.each do |version|
+    (@all_versions - [nil]).each do |version|
       data = {
         "a" => "23"
       }
       schema = @schemas[version]
-      prefix = "Validation for '#{version}'"
+      prefix = "Validation for '#{version || 'default'}'"
 
       assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with no 'custom' format validator registered")
 
@@ -89,13 +90,13 @@ def test_format_validation
   end
 
   def test_override_default_format
-    @all_versions.each do |version|
+    (@all_versions - [nil]).each do |version|
       data = {
         "a" => "2001:db8:85a3:0:0:8a2e:370:7334"
       }
       schema = @schemas[version]
       schema["properties"]["a"]["format"] = "ipv6"
-      prefix = "Validation for '#{version}'"
+      prefix = "Validation for '#{version || 'default'}'"
 
       assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds for default format with correct data")
 

From 84012d872b21d9be584aeba16a3e7fae6c0ff11d Mon Sep 17 00:00:00 2001
From: James McKinney 
Date: Tue, 24 Nov 2015 03:09:01 -0500
Subject: [PATCH 09/43] register_format_validator on default_validator

---
 lib/json-schema/validator.rb | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb
index 6453dade..e22943ee 100644
--- a/lib/json-schema/validator.rb
+++ b/lib/json-schema/validator.rb
@@ -373,20 +373,20 @@ def register_default_validator(v)
         @@default_validator = v
       end
 
-      def register_format_validator(format, validation_proc, versions = ["draft1", "draft2", "draft3", "draft4"])
+      def register_format_validator(format, validation_proc, versions = ["draft1", "draft2", "draft3", "draft4", nil])
         custom_format_validator = JSON::Schema::CustomFormat.new(validation_proc)
         validators_for_names(versions).each do |validator|
           validator.formats[format.to_s] = custom_format_validator
         end
       end
 
-      def deregister_format_validator(format, versions = ["draft1", "draft2", "draft3", "draft4"])
+      def deregister_format_validator(format, versions = ["draft1", "draft2", "draft3", "draft4", nil])
         validators_for_names(versions).each do |validator|
           validator.formats[format.to_s] = validator.default_formats[format.to_s]
         end
       end
 
-      def restore_default_formats(versions = ["draft1", "draft2", "draft3", "draft4"])
+      def restore_default_formats(versions = ["draft1", "draft2", "draft3", "draft4", nil])
         validators_for_names(versions).each do |validator|
           validator.formats = validator.default_formats.clone
         end
@@ -482,9 +482,16 @@ def merge_missing_values(source, destination)
       private
 
       def validators_for_names(names)
-        names.map! { |name| name.to_s }
-        validators.reduce([]) do |memo, (_, validator)|
-          memo.tap { |m| m << validator if (validator.names & names).any? }
+        names = names.map { |name| name.to_s }
+        [].tap do |memo|
+          validators.each do |_, validator|
+            if (validator.names & names).any?
+              memo << validator
+            end
+          end
+          if names.include?('')
+            memo << default_validator
+          end
         end
       end
     end

From 8960753d88011afdfc9c0f2b9e4c78cbbb00309b Mon Sep 17 00:00:00 2001
From: James McKinney 
Date: Tue, 24 Nov 2015 03:31:12 -0500
Subject: [PATCH 10/43] Add a schema for default_validator in
 test_custom_format

---
 test/test-suite            | 2 +-
 test/test_custom_format.rb | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/test/test-suite b/test/test-suite
index 8f867168..5bcf11a5 160000
--- a/test/test-suite
+++ b/test/test-suite
@@ -1 +1 @@
-Subproject commit 8f867168d17497a775141704960906db83634a04
+Subproject commit 5bcf11a510da88290375a6cbacf957f33bffa6de
diff --git a/test/test_custom_format.rb b/test/test_custom_format.rb
index a53f165a..fb689646 100644
--- a/test/test_custom_format.rb
+++ b/test/test_custom_format.rb
@@ -21,11 +21,13 @@ def setup
     @schema_1 = @schema_4.clone
     @schema_1["$schema"] = "http://json-schema.org/draft-01/schema#"
     @default = @schema_4.clone
+    @default.delete("$schema")
     @schemas = {
       "draft1" => @schema_1,
       "draft2" => @schema_2,
       "draft3" => @schema_3,
       "draft4" => @schema_4,
+      nil => @default,
     }
     JSON::Validator.restore_default_formats
   end

From fa7776dd7eaadd49ec43093ae9fcfbcedf698af1 Mon Sep 17 00:00:00 2001
From: Kenny Hoxworth 
Date: Tue, 24 Nov 2015 08:38:25 -0800
Subject: [PATCH 11/43] Bump version

---
 README.textile  | 2 +-
 VERSION.yml     | 2 +-
 test/test-suite | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.textile b/README.textile
index 42827d67..0f207b7f 100644
--- a/README.textile
+++ b/README.textile
@@ -26,7 +26,7 @@ From the git repo:
 
 
 $ gem build json-schema.gemspec
-$ gem install json-schema-2.5.0.gem
+$ gem install json-schema-2.5.2.gem
 
diff --git a/VERSION.yml b/VERSION.yml index 10e76f93..1d7cbb09 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,3 +1,3 @@ major: 2 minor: 5 -patch: 1 +patch: 2 diff --git a/test/test-suite b/test/test-suite index 5bcf11a5..c73cf222 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 5bcf11a510da88290375a6cbacf957f33bffa6de +Subproject commit c73cf2225e3be05ba0a455e990309539c49ebc51 From 5b80c538908de4124d512685be8bcd9297515d83 Mon Sep 17 00:00:00 2001 From: James McKinney Date: Tue, 24 Nov 2015 12:34:55 -0500 Subject: [PATCH 12/43] Test all versions in test_custom_format --- test/test_custom_format.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_custom_format.rb b/test/test_custom_format.rb index fb689646..794383e5 100644 --- a/test/test_custom_format.rb +++ b/test/test_custom_format.rb @@ -66,7 +66,7 @@ def test_multi_registration end def test_format_validation - (@all_versions - [nil]).each do |version| + @all_versions.each do |version| data = { "a" => "23" } @@ -92,7 +92,7 @@ def test_format_validation end def test_override_default_format - (@all_versions - [nil]).each do |version| + @all_versions.each do |version| data = { "a" => "2001:db8:85a3:0:0:8a2e:370:7334" } From 0d262057ee8fb333cb5a0c295608d1475b0235ba Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Tue, 22 Dec 2015 10:55:11 +0000 Subject: [PATCH 13/43] Updated common test suite --- test/test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-suite b/test/test-suite index c73cf222..5dc71b8c 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit c73cf2225e3be05ba0a455e990309539c49ebc51 +Subproject commit 5dc71b8cbc7513b433f6adcd61a5cfcdc0c45442 From 31a620b7e9e6f7b908e989b365d86a94b75a9b66 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 23 Dec 2015 08:01:21 +0000 Subject: [PATCH 14/43] Added a changelog --- CHANGELOG.md | 12 ++++++++++++ CONTRIBUTING.md | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..e73b7925 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Change Log +All notable changes to this project will be documented in this file. +Please keep to the changelog format described on [keepachangelog.com](http://keepachangelog.com). +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] +### Added +- Added a changelog + +### Changed +- Made validation failures raise a `JSON::Schema::SchemaParseError` and data + loading failures a `JSON::Schema::JsonLoadError` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ca5c4d57..1b2df766 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,6 @@ The Ruby JSON Schema library is meant to be a community effort, and as such, the All individuals that have a pull request merged will receive collaborator access to the repository. Due to the restrictions on RubyGems authentication, permissions to release a gem must be requested along with the email desired to be associated with the release credentials. -Accepting changes to the JSON Schema library shall be made through the use of pull requests on GitHub. A pull request must receive at least two (2) "+1" comments from current contributors to the JSON Schema library before being accepted and merged. If a breaking issue and fix exists, please feel free to contact the project maintainer at hoxworth@gmail.com or @hoxworth for faster resolution. +Accepting changes to the JSON Schema library shall be made through the use of pull requests on GitHub. A pull request must receive at least two (2) "+1" comments from current contributors, and include a relevant changelog entry, before being accepted and merged. If a breaking issue and fix exists, please feel free to contact the project maintainer at hoxworth@gmail.com or @hoxworth for faster resolution. Releases follow semantic versioning and may be made at a maintainer's discretion. From d89890515290e881d40ce884fcc2182c665809fa Mon Sep 17 00:00:00 2001 From: "Michael J. Cohen" Date: Thu, 14 May 2015 13:33:27 -0600 Subject: [PATCH 15/43] Speed up JSON::Validator.validate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addressible's URI parsing shows up at the top of the profiler for our use case. This patch adds a cache to JSON::Util::URI.normalized_uri, to trade CPU time for memory. There are other expensive Addressible methods that should be cached elsewhere. benchmark: https://github.com/mjc/json-schema-perf MRI 2.2.2 before: 825.363 (± 6.2%) i/s MRI 2.2.2 after: 1.436k (± 4.5%) i/s 1.74x faster JRuby 1.7.20 before: 1.445k (± 2.5%) i/s JRuby 1.7.20 after: 2.272k (± 6.1%) i/s 1.57x faster --- CHANGELOG.md | 1 + lib/json-schema/attributes/formats/uri.rb | 2 +- lib/json-schema/attributes/ref.rb | 29 +++++++------- lib/json-schema/schema.rb | 3 +- lib/json-schema/schema/reader.rb | 2 +- lib/json-schema/util/uri.rb | 45 ++++++++++++++++++---- lib/json-schema/validator.rb | 16 ++++---- lib/json-schema/validators/draft1.rb | 8 ++-- lib/json-schema/validators/draft2.rb | 8 ++-- lib/json-schema/validators/draft3.rb | 8 ++-- lib/json-schema/validators/draft4.rb | 2 +- lib/json-schema/validators/hyper-draft1.rb | 2 +- lib/json-schema/validators/hyper-draft2.rb | 2 +- lib/json-schema/validators/hyper-draft4.rb | 2 +- 14 files changed, 81 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e73b7925..ddea5fc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,5 +8,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added a changelog ### Changed +- Improved performance by caching the parsing and normalization of URIs - Made validation failures raise a `JSON::Schema::SchemaParseError` and data loading failures a `JSON::Schema::JsonLoadError` diff --git a/lib/json-schema/attributes/formats/uri.rb b/lib/json-schema/attributes/formats/uri.rb index ff74ad7d..7105bf27 100644 --- a/lib/json-schema/attributes/formats/uri.rb +++ b/lib/json-schema/attributes/formats/uri.rb @@ -7,7 +7,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options return unless data.is_a?(String) error_message = "The property '#{build_fragment(fragments)}' must be a valid URI" begin - Addressable::URI.parse(data) + JSON::Util::URI.parse(data) rescue Addressable::URI::InvalidURIError validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end diff --git a/lib/json-schema/attributes/ref.rb b/lib/json-schema/attributes/ref.rb index a537cffe..3a7ab346 100644 --- a/lib/json-schema/attributes/ref.rb +++ b/lib/json-schema/attributes/ref.rb @@ -1,5 +1,6 @@ require 'json-schema/attribute' require 'json-schema/errors/schema_error' +require 'json-schema/util/uri' module JSON class Schema @@ -21,21 +22,23 @@ def self.validate(current_schema, data, fragments, processor, validator, options def self.get_referenced_uri_and_schema(s, current_schema, validator) uri,schema = nil,nil - temp_uri = Addressable::URI.parse(s['$ref']) - if temp_uri.relative? - temp_uri = current_schema.uri.clone - # Check for absolute path - path = s['$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) + temp_uri = JSON::Util::URI.parse(s['$ref']) + temp_uri.defer_validation do + if temp_uri.relative? + temp_uri.merge!(current_schema.uri) + # Check for absolute path + path, fragment = s['$ref'].split("#") + 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.join!(path) + end + temp_uri.fragment = fragment end - temp_uri.fragment = s['$ref'].split("#")[1] + temp_uri.fragment = "" if temp_uri.fragment.nil? || temp_uri.fragment.empty? 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] + "#" diff --git a/lib/json-schema/schema.rb b/lib/json-schema/schema.rb index cba7bac0..443a1f0f 100644 --- a/lib/json-schema/schema.rb +++ b/lib/json-schema/schema.rb @@ -11,7 +11,7 @@ def initialize(schema,uri,parent_validator=nil) # If there is an ID on this schema, use it to generate the URI if @schema['id'] && @schema['id'].kind_of?(String) - temp_uri = Addressable::URI.parse(@schema['id']) + temp_uri = JSON::Util::URI.parse(@schema['id']) if temp_uri.relative? temp_uri = uri.join(temp_uri) end @@ -60,4 +60,3 @@ def to_s end end end - diff --git a/lib/json-schema/schema/reader.rb b/lib/json-schema/schema/reader.rb index 4121bf99..1ddf42a2 100644 --- a/lib/json-schema/schema/reader.rb +++ b/lib/json-schema/schema/reader.rb @@ -60,7 +60,7 @@ def initialize(options = {}) # indicated the schema could not be read # @raise [JSON::Schema::ParseError] if the schema was not a valid JSON object def read(location) - uri = Addressable::URI.parse(location.to_s) + uri = JSON::Util::URI.parse(location.to_s) body = if uri.scheme.nil? || uri.scheme == 'file' uri = Addressable::URI.convert_path(uri.path) read_file(Pathname.new(uri.path).expand_path) diff --git a/lib/json-schema/util/uri.rb b/lib/json-schema/util/uri.rb index 951c2ce9..56106f2f 100644 --- a/lib/json-schema/util/uri.rb +++ b/lib/json-schema/util/uri.rb @@ -3,15 +3,44 @@ module Util module URI SUPPORTED_PROTOCOLS = %w(http https ftp tftp sftp ssh svn+ssh telnet nntp gopher wais ldap prospero) - def self.normalized_uri(uri) - uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI) - # Check for absolute path - if uri.relative? - data = uri.to_s - data = "#{Dir.pwd}/#{data}" if data[0,1] != '/' - uri = Addressable::URI.convert_path(data) + def self.normalized_uri(uri, base_path = Dir.pwd) + @normalize_cache ||= {} + normalized_uri = @normalize_cache[uri] + + if !normalized_uri + normalized_uri = parse(uri) + # Check for absolute path + if normalized_uri.relative? + data = normalized_uri + data = File.join(base_path, data) if data.path[0,1] != "/" + normalized_uri = Addressable::URI.convert_path(data) + end + @normalize_cache[uri] = normalized_uri.freeze + end + + normalized_uri + end + + def self.parse(uri) + if uri.is_a?(Addressable::URI) + return uri.dup + else + @parse_cache ||= {} + parsed_uri = @parse_cache[uri] + if parsed_uri + parsed_uri.dup + else + @parse_cache[uri] = Addressable::URI.parse(uri) + end + end + end + + def self.strip_fragment(uri) + if uri.fragment.nil? || uri.fragment.empty? + uri + else + uri.merge(:fragment => "") end - uri end end end diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 495e6e1e..5acf43cf 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -12,6 +12,7 @@ require 'json-schema/errors/schema_parse_error' require 'json-schema/errors/json_load_error' require 'json-schema/errors/json_parse_error' +require 'json-schema/util/uri' module JSON @@ -136,15 +137,14 @@ def load_ref_schema(parent_schema, ref) end def absolutize_ref_uri(ref, parent_schema_uri) - ref_uri = Addressable::URI.parse(ref) + ref_uri = JSON::Util::URI.parse(ref) ref_uri.fragment = '' return ref_uri if ref_uri.absolute? # This is a self reference and thus the schema does not need to be re-loaded return parent_schema_uri if ref_uri.path.empty? - uri = parent_schema_uri.clone - uri.fragment = '' + uri = JSON::Util::URI.strip_fragment(parent_schema_uri.dup) Util::URI.normalized_uri(uri.join(ref_uri.path)) end @@ -220,7 +220,7 @@ def build_schemas(parent_schema) # Either load a reference schema or create a new schema def handle_schema(parent_schema, obj) if obj.is_a?(Hash) - schema_uri = parent_schema.uri.clone + schema_uri = parent_schema.uri.dup schema = JSON::Schema.new(obj, schema_uri, parent_schema.validator) if obj['id'] Validator.add_schema(schema) @@ -342,7 +342,7 @@ def default_validator def validator_for_uri(schema_uri) return default_validator unless schema_uri - u = Addressable::URI.parse(schema_uri) + u = JSON::Util::URI.parse(schema_uri) validator = validators["#{u.scheme}://#{u.host}#{u.path}"] if validator.nil? raise JSON::Schema::SchemaError.new("Schema not found: #{schema_uri}") @@ -532,7 +532,7 @@ 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_uri = JSON::Util::URI.parse(fake_uuid(schema)) schema = JSON::Schema.new(JSON::Validator.parse(schema), schema_uri, @options[:version]) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema @@ -554,14 +554,14 @@ def initialize_schema(schema) schema = self.class.schema_for_uri(schema_uri) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema - schema.uri = Addressable::URI.parse(fake_uuid(serialize(schema.schema))) + schema.uri = JSON::Util::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_uri = JSON::Util::URI.parse(fake_uuid(serialize(schema))) schema = JSON::Schema.stringify(schema) schema = JSON::Schema.new(schema, schema_uri, @options[:version]) if @options[:list] && @options[:fragment].nil? diff --git a/lib/json-schema/validators/draft1.rb b/lib/json-schema/validators/draft1.rb index 25910a77..aca51efa 100644 --- a/lib/json-schema/validators/draft1.rb +++ b/lib/json-schema/validators/draft1.rb @@ -2,7 +2,7 @@ module JSON class Schema - + class Draft1 < Validator def initialize super @@ -33,13 +33,13 @@ def initialize 'uri' => UriFormat } @formats = @default_formats.clone - @uri = Addressable::URI.parse("http://json-schema.org/draft-01/schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-01/schema#") @names = ["draft1"] @metaschema_name = "draft-01.json" end - + JSON::Validator.register_validator(self.new) end - + end end diff --git a/lib/json-schema/validators/draft2.rb b/lib/json-schema/validators/draft2.rb index 4f12ae7a..82825d57 100644 --- a/lib/json-schema/validators/draft2.rb +++ b/lib/json-schema/validators/draft2.rb @@ -2,7 +2,7 @@ module JSON class Schema - + class Draft2 < Validator def initialize super @@ -34,13 +34,13 @@ def initialize 'uri' => UriFormat } @formats = @default_formats.clone - @uri = Addressable::URI.parse("http://json-schema.org/draft-02/schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-02/schema#") @names = ["draft2"] @metaschema_name = "draft-02.json" end - + JSON::Validator.register_validator(self.new) end - + end end diff --git a/lib/json-schema/validators/draft3.rb b/lib/json-schema/validators/draft3.rb index 572cbabc..6d0784ea 100644 --- a/lib/json-schema/validators/draft3.rb +++ b/lib/json-schema/validators/draft3.rb @@ -2,7 +2,7 @@ module JSON class Schema - + class Draft3 < Validator def initialize super @@ -38,13 +38,13 @@ def initialize 'uri' => UriFormat } @formats = @default_formats.clone - @uri = Addressable::URI.parse("http://json-schema.org/draft-03/schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-03/schema#") @names = ["draft3", "http://json-schema.org/draft-03/schema#"] @metaschema_name = "draft-03.json" end - + JSON::Validator.register_validator(self.new) end - + end end diff --git a/lib/json-schema/validators/draft4.rb b/lib/json-schema/validators/draft4.rb index dac27f2c..904cdf37 100644 --- a/lib/json-schema/validators/draft4.rb +++ b/lib/json-schema/validators/draft4.rb @@ -43,7 +43,7 @@ def initialize 'uri' => UriFormat } @formats = @default_formats.clone - @uri = Addressable::URI.parse("http://json-schema.org/draft-04/schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-04/schema#") @names = ["draft4", "http://json-schema.org/draft-04/schema#"] @metaschema_name = "draft-04.json" end diff --git a/lib/json-schema/validators/hyper-draft1.rb b/lib/json-schema/validators/hyper-draft1.rb index 2eabe9a4..6b26daa8 100644 --- a/lib/json-schema/validators/hyper-draft1.rb +++ b/lib/json-schema/validators/hyper-draft1.rb @@ -4,7 +4,7 @@ class Schema class HyperDraft1 < Draft1 def initialize super - @uri = Addressable::URI.parse("http://json-schema.org/draft-01/hyper-schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-01/hyper-schema#") end JSON::Validator.register_validator(self.new) diff --git a/lib/json-schema/validators/hyper-draft2.rb b/lib/json-schema/validators/hyper-draft2.rb index be02bc7d..86b5ed81 100644 --- a/lib/json-schema/validators/hyper-draft2.rb +++ b/lib/json-schema/validators/hyper-draft2.rb @@ -4,7 +4,7 @@ class Schema class HyperDraft2 < Draft2 def initialize super - @uri = Addressable::URI.parse("http://json-schema.org/draft-02/hyper-schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-02/hyper-schema#") end JSON::Validator.register_validator(self.new) diff --git a/lib/json-schema/validators/hyper-draft4.rb b/lib/json-schema/validators/hyper-draft4.rb index d39b183f..fdc10f3a 100644 --- a/lib/json-schema/validators/hyper-draft4.rb +++ b/lib/json-schema/validators/hyper-draft4.rb @@ -4,7 +4,7 @@ class Schema class HyperDraft4 < Draft4 def initialize super - @uri = Addressable::URI.parse("http://json-schema.org/draft-04/hyper-schema#") + @uri = JSON::Util::URI.parse("http://json-schema.org/draft-04/hyper-schema#") end JSON::Validator.register_validator(self.new) From 46abf887c33b5055af749996141a3828be1ec8bd Mon Sep 17 00:00:00 2001 From: "Michael J. Cohen" Date: Mon, 18 May 2015 16:44:19 -0600 Subject: [PATCH 16/43] Don't use YAML when JSON.dump will do --- lib/json-schema/validator.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 5acf43cf..158d6537 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -484,6 +484,8 @@ def merge_missing_values(source, destination) if @@json_backend == 'yajl' @@serializer = lambda{|o| Yajl::Encoder.encode(o) } + elsif @@json_backend == 'json' + @@serializer = lambda{|o| JSON.dump(o) } else @@serializer = lambda{|o| YAML.dump(o) } end From ba169396cd0c99c745be5d39e5a9e0dcd18bc3d0 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 23 Dec 2015 09:53:37 +0000 Subject: [PATCH 17/43] Don't update url fragment if it's already blank or nil Addressable::URI#fragment= triggers a revalidation of the URL, which is super slow. Don't do this when it isn't necessary. --- lib/json-schema/schema.rb | 2 +- lib/json-schema/util/uri.rb | 7 ++++--- lib/json-schema/validator.rb | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/json-schema/schema.rb b/lib/json-schema/schema.rb index 443a1f0f..1df0623b 100644 --- a/lib/json-schema/schema.rb +++ b/lib/json-schema/schema.rb @@ -17,7 +17,7 @@ def initialize(schema,uri,parent_validator=nil) end @uri = temp_uri end - @uri.fragment = '' + @uri = JSON::Util::URI.strip_fragment(@uri) # If there is a $schema on this schema, use it to determine which validator to use if @schema['$schema'] diff --git a/lib/json-schema/util/uri.rb b/lib/json-schema/util/uri.rb index 56106f2f..f2d2452e 100644 --- a/lib/json-schema/util/uri.rb +++ b/lib/json-schema/util/uri.rb @@ -36,10 +36,11 @@ def self.parse(uri) end def self.strip_fragment(uri) - if uri.fragment.nil? || uri.fragment.empty? - uri + parsed_uri = parse(uri) + if parsed_uri.fragment.nil? || parsed_uri.fragment.empty? + parsed_uri else - uri.merge(:fragment => "") + parsed_uri.merge(:fragment => "") end end end diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 158d6537..03a81e02 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -137,8 +137,7 @@ def load_ref_schema(parent_schema, ref) end def absolutize_ref_uri(ref, parent_schema_uri) - ref_uri = JSON::Util::URI.parse(ref) - ref_uri.fragment = '' + ref_uri = JSON::Util::URI.strip_fragment(ref) return ref_uri if ref_uri.absolute? # This is a self reference and thus the schema does not need to be re-loaded From 6967d993ef9a08b0f19ad011275791c28e6b75e0 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 23 Dec 2015 19:33:26 +0000 Subject: [PATCH 18/43] Removed all references to Addressable outside JSON::Util::URI Hopefully this will make it easier to change in future --- lib/json-schema/attributes/formats/uri.rb | 5 +++-- lib/json-schema/attributes/ref.rb | 2 +- lib/json-schema/errors/uri_error.rb | 6 ++++++ lib/json-schema/schema/reader.rb | 5 ++--- lib/json-schema/util/uri.rb | 18 +++++++++++++++++- lib/json-schema/validator.rb | 3 +-- 6 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 lib/json-schema/errors/uri_error.rb diff --git a/lib/json-schema/attributes/formats/uri.rb b/lib/json-schema/attributes/formats/uri.rb index 7105bf27..17e989ea 100644 --- a/lib/json-schema/attributes/formats/uri.rb +++ b/lib/json-schema/attributes/formats/uri.rb @@ -1,5 +1,6 @@ require 'json-schema/attribute' -require 'addressable/uri' +require 'json-schema/errors/uri_error' + module JSON class Schema class UriFormat < FormatAttribute @@ -8,7 +9,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options error_message = "The property '#{build_fragment(fragments)}' must be a valid URI" begin JSON::Util::URI.parse(data) - rescue Addressable::URI::InvalidURIError + rescue JSON::Schema::UriError validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end diff --git a/lib/json-schema/attributes/ref.rb b/lib/json-schema/attributes/ref.rb index 3a7ab346..508f7340 100644 --- a/lib/json-schema/attributes/ref.rb +++ b/lib/json-schema/attributes/ref.rb @@ -52,7 +52,7 @@ def self.get_referenced_uri_and_schema(s, current_schema, validator) fragment_path = '' fragments.each do |fragment| if fragment && fragment != '' - fragment = Addressable::URI.unescape(fragment.gsub('~0', '~').gsub('~1', '/')) + fragment = JSON::Util::URI.unescaped_uri(fragment.gsub('~0', '~').gsub('~1', '/')) if target_schema.is_a?(Array) target_schema = target_schema[fragment.to_i] else diff --git a/lib/json-schema/errors/uri_error.rb b/lib/json-schema/errors/uri_error.rb new file mode 100644 index 00000000..cf4d306b --- /dev/null +++ b/lib/json-schema/errors/uri_error.rb @@ -0,0 +1,6 @@ +module JSON + class Schema + class UriError < StandardError + end + end +end diff --git a/lib/json-schema/schema/reader.rb b/lib/json-schema/schema/reader.rb index 1ddf42a2..ae7bdf41 100644 --- a/lib/json-schema/schema/reader.rb +++ b/lib/json-schema/schema/reader.rb @@ -1,5 +1,4 @@ require 'open-uri' -require 'addressable/uri' require 'pathname' module JSON @@ -62,7 +61,7 @@ def initialize(options = {}) def read(location) uri = JSON::Util::URI.parse(location.to_s) body = if uri.scheme.nil? || uri.scheme == 'file' - uri = Addressable::URI.convert_path(uri.path) + uri = JSON::Util::URI.file_uri(uri) read_file(Pathname.new(uri.path).expand_path) else read_uri(uri) @@ -103,7 +102,7 @@ def read_uri(uri) def read_file(pathname) if accept_file?(pathname) - File.read(Addressable::URI.unescape(pathname.to_s)) + File.read(JSON::Util::URI.unescaped_uri(pathname.to_s)) else raise JSON::Schema::ReadRefused.new(pathname.to_s, :file) end diff --git a/lib/json-schema/util/uri.rb b/lib/json-schema/util/uri.rb index f2d2452e..4ddf2ea7 100644 --- a/lib/json-schema/util/uri.rb +++ b/lib/json-schema/util/uri.rb @@ -1,3 +1,5 @@ +require 'addressable/uri' + module JSON module Util module URI @@ -13,7 +15,7 @@ def self.normalized_uri(uri, base_path = Dir.pwd) if normalized_uri.relative? data = normalized_uri data = File.join(base_path, data) if data.path[0,1] != "/" - normalized_uri = Addressable::URI.convert_path(data) + normalized_uri = file_uri(data) end @normalize_cache[uri] = normalized_uri.freeze end @@ -33,6 +35,8 @@ def self.parse(uri) @parse_cache[uri] = Addressable::URI.parse(uri) end end + rescue Addressable::URI::InvalidURIError => e + raise JSON::Schema::UriError.new(e.message) end def self.strip_fragment(uri) @@ -43,6 +47,18 @@ def self.strip_fragment(uri) parsed_uri.merge(:fragment => "") end end + + def self.file_uri(uri) + parsed_uri = parse(uri) + + Addressable::URI.convert_path(parsed_uri.path) + end + + def self.unescaped_uri(uri) + parsed_uri = parse(uri) + + Addressable::URI.unescape(parsed_uri.path) + end end end end diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 03a81e02..a447fcc5 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -1,4 +1,3 @@ -require 'addressable/uri' require 'open-uri' require 'pathname' require 'bigdecimal' @@ -609,7 +608,7 @@ def custom_open(uri) end else begin - File.read(Addressable::URI.unescape(uri.path)) + File.read(JSON::Util::URI.unescaped_uri(uri)) rescue SystemCallError => e raise JSON::Schema::JsonLoadError, e.message end From 111f16e70d5ac5a2cf93c6a4b8979fb81243c702 Mon Sep 17 00:00:00 2001 From: Teo Ljungberg Date: Thu, 24 Dec 2015 12:08:11 +0100 Subject: [PATCH 19/43] Remove ruby warnings For the unused variable `validator` --- test/test_load_ref_schema.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/test_load_ref_schema.rb b/test/test_load_ref_schema.rb index f37942dc..9af9a7a1 100644 --- a/test/test_load_ref_schema.rb +++ b/test/test_load_ref_schema.rb @@ -18,23 +18,21 @@ def load_other_schema def test_cached_schema schema_url = "http://example.com/schema#" - schema = { - "$ref" => schema_url - } + schema = { "$ref" => schema_url } data = {} load_other_schema - validator = JSON::Validator.new(schema, data) + _validator = JSON::Validator.new(schema, data) + assert JSON::Validator.schema_loaded?(schema_url) end def test_cached_schema_with_fragment schema_url = "http://example.com/schema#" - schema = { - "$ref" => "#{schema_url}/properties/title" - } + schema = { "$ref" => "#{schema_url}/properties/title" } data = {} load_other_schema - validator = JSON::Validator.new(schema, data) + _validator = JSON::Validator.new(schema, data) + assert JSON::Validator.schema_loaded?(schema_url) end end From da77b70e680eee168e0afc37f654bfbd4125d3ed Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 8 Jan 2016 10:52:17 +0000 Subject: [PATCH 20/43] Updated common test suite --- test/test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-suite b/test/test-suite index 5dc71b8c..9723c8f2 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 5dc71b8cbc7513b433f6adcd61a5cfcdc0c45442 +Subproject commit 9723c8f2f5f7c471c5147d5d6d08f4aa10a89f83 From f4183cfdc4c0edb40f7a467c21ba3164098482ff Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 8 Jan 2016 10:52:52 +0000 Subject: [PATCH 21/43] Added ruby 2.3 to the travis build --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8036dfb..d374f3bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ rvm: - "2.0" - "2.1" - "2.2" + - "2.3" - "jruby" - "rbx" @@ -16,11 +17,11 @@ install: matrix: include: - - rvm: "2.2" + - rvm: "2.3" gemfile: "gemfiles/Gemfile.multi_json.x" - - rvm: "2.2" + - rvm: "2.3" gemfile: "gemfiles/Gemfile.yajl-ruby.x" - - rvm: "2.2" + - rvm: "2.3" gemfile: "gemfiles/Gemfile.uuidtools.x" allow_failures: - rvm: "1.8" From 0dc351088f509939c7be98f0f47ccf5131d5433f Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 8 Jan 2016 10:59:45 +0000 Subject: [PATCH 22/43] Corrected ruby 2.3 build on travis --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d374f3bd..e027c911 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ rvm: - "2.0" - "2.1" - "2.2" - - "2.3" + - "2.3.0" - "jruby" - "rbx" @@ -17,11 +17,11 @@ install: matrix: include: - - rvm: "2.3" + - rvm: "2.3.0" gemfile: "gemfiles/Gemfile.multi_json.x" - - rvm: "2.3" + - rvm: "2.3.0" gemfile: "gemfiles/Gemfile.yajl-ruby.x" - - rvm: "2.3" + - rvm: "2.3.0" gemfile: "gemfiles/Gemfile.uuidtools.x" allow_failures: - rvm: "1.8" From 597952b0328a1c8a82507528eb9e795a323f995e Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 8 Jan 2016 11:11:04 +0000 Subject: [PATCH 23/43] Bumped version to 2.6.0 --- VERSION.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION.yml b/VERSION.yml index 1d7cbb09..e9a7eddb 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,3 +1,3 @@ major: 2 -minor: 5 -patch: 2 +minor: 6 +patch: 0 From c3c46a6d63450eefa70c9e0673df2a5be937ae5b Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Thu, 14 Jan 2016 10:44:50 +0000 Subject: [PATCH 24/43] Made sure we include the module name for SchemaParseErrors If you pass an unrecognized object for the schema, we should be raising a SchemaParseError, however instead right now a NameError is raised, beacuse we're not correctly qualifying the error class with it's module. I've corrected the class/module name and added tests. This fixes #292 --- lib/json-schema/validator.rb | 2 +- test/test_ruby_schema.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index a447fcc5..50b5b07f 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -569,7 +569,7 @@ def initialize_schema(schema) end Validator.add_schema(schema) else - raise SchemaParseError, "Invalid schema - must be either a string or a hash" + raise JSON::Schema::SchemaParseError, "Invalid schema - must be either a string or a hash" end schema diff --git a/test/test_ruby_schema.rb b/test/test_ruby_schema.rb index 7693b336..a6e884bd 100644 --- a/test/test_ruby_schema.rb +++ b/test/test_ruby_schema.rb @@ -56,4 +56,10 @@ def test_symbol_keys_in_hash_within_array assert_valid schema, data, :validate_schema => true end + + def test_schema_of_unrecognized_type + assert_raises JSON::Schema::SchemaParseError do + JSON::Validator.validate(Object.new, {}) + end + end end From dbcf20706fcd0440d0098836e21797a1ad03e538 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Thu, 14 Jan 2016 18:13:25 +0000 Subject: [PATCH 25/43] Updated changelog for w --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddea5fc8..ec6f7680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Please keep to the changelog format described on [keepachangelog.com](http://kee This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] + + +## [2.6.0] - 2016-01-08 + ### Added - Added a changelog From 2414110fc3e553d5d9107cbcc287a0125ab4c4a7 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Thu, 14 Jan 2016 18:15:50 +0000 Subject: [PATCH 26/43] Updated changelog for #293 Forgot to do this in the PR --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec6f7680..aa818ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +- Made sure schemas of an unrecognized type raise a SchemaParseError (not Name error) ## [2.6.0] - 2016-01-08 From a1e0aece786da139992bc1e02020dfcb3289086e Mon Sep 17 00:00:00 2001 From: Jonas Peschla Date: Thu, 11 Feb 2016 23:58:09 +0100 Subject: [PATCH 27/43] Fetch upstream --- test/test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-suite b/test/test-suite index 9723c8f2..9208016d 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 9723c8f2f5f7c471c5147d5d6d08f4aa10a89f83 +Subproject commit 9208016d04c1b6774d5a17e8b037161873414edb From 11bd6d9ea5d27696f5bf96be3f96db0d7d423653 Mon Sep 17 00:00:00 2001 From: Jonas Peschla Date: Fri, 12 Feb 2016 18:50:22 +0100 Subject: [PATCH 28/43] Update subproject --- test/test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-suite b/test/test-suite index 9208016d..9723c8f2 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 9208016d04c1b6774d5a17e8b037161873414edb +Subproject commit 9723c8f2f5f7c471c5147d5d6d08f4aa10a89f83 From 301c407d169eacb9f066635446f484fbe5a11848 Mon Sep 17 00:00:00 2001 From: Joe Lencioni Date: Sun, 31 Jan 2016 10:57:37 -0800 Subject: [PATCH 29/43] Convert README.textile to markdown and improve format This started as a straight up automated conversion via pandoc: pandoc README.textile -o README.md I then followed up by fixing the images it did not convert properly, removing extraneous backslashes that it added, and adding finced code blocks for syntax highlighting. I also replaced ... with backticks and adjusted some whitespace. --- README.textile => README.md | 310 ++++++++++++++++++++++-------------- json-schema.gemspec | 2 +- 2 files changed, 190 insertions(+), 122 deletions(-) rename README.textile => README.md (51%) diff --git a/README.textile b/README.md similarity index 51% rename from README.textile rename to README.md index ce6f8028..f14fe25a 100644 --- a/README.textile +++ b/README.md @@ -1,48 +1,80 @@ -!https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master!:https://travis-ci.org/ruby-json-schema/json-schema -!https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg!:https://codeclimate.com/github/ruby-json-schema/json-schema +![https://travis-ci.org/ruby-json-schema/json-schema](https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master) +![https://codeclimate.com/github/ruby-json-schema/json-schema](https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg) -h1. Ruby JSON Schema Validator +Ruby JSON Schema Validator +========================== -This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04. Legacy support for "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03, "JSON Schema Draft 2":http://tools.ietf.org/html/draft-zyp-json-schema-02, and "JSON Schema Draft 1":http://tools.ietf.org/html/draft-zyp-json-schema-01 is also included. +This library is intended to provide Ruby with an interface for validating JSON +objects against a JSON schema conforming to [JSON Schema Draft +4](http://tools.ietf.org/html/draft-zyp-json-schema-04). Legacy support for +[JSON Schema Draft 3](http://tools.ietf.org/html/draft-zyp-json-schema-03), +[JSON Schema Draft 2](http://tools.ietf.org/html/draft-zyp-json-schema-02), and +[JSON Schema Draft 1](http://tools.ietf.org/html/draft-zyp-json-schema-01) is +also included. -h2. Additional Resources +Additional Resources +-------------------- -* "Google Groups":https://groups.google.com/forum/#!forum/ruby-json-schema -* #ruby-json-schema on chat.freenode.net +- [Google Groups](https://groups.google.com/forum/#!forum/ruby-json-schema) +- #ruby-json-schema on chat.freenode.net -h2. Version 2.0.0 Upgrade Notes +Version 2.0.0 Upgrade Notes +--------------------------- -Please be aware that the upgrade to version 2.0.0 will use Draft-04 *by default*, so schemas that do not declare a validator using the $schema keyword will use Draft-04 now instead of Draft-03. This is the reason for the major version upgrade. +Please be aware that the upgrade to version 2.0.0 will use Draft-04 **by +default**, so schemas that do not declare a validator using the `$schema` +keyword will use Draft-04 now instead of Draft-03. This is the reason for the +major version upgrade. -h2. Installation +Installation +------------ From rubygems.org: -
+```sh
 gem install json-schema
-
+``` From the git repo: -
+```sh
 $ gem build json-schema.gemspec
 $ gem install json-schema-2.5.2.gem
-
- - -h2. Usage - -Three base validation methods exist: validate, validate!, and fully_validate. The first returns a boolean on whether a validation attempt passes and the second will throw a JSON::Schema::ValidationError with an appropriate message/trace on where the validation failed. The third validation method does not immediately fail upon a validation error and instead builds an array of validation errors return when validation is complete. - -All methods take two arguments, which can be either a JSON string, a file containing JSON, or a Ruby object representing JSON data. The first argument to these methods is always the schema, the second is always the data to validate. An optional third options argument is also accepted; available options are used in the examples below. - -By default, the validator uses the "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04 specification for validation; however, the user is free to specify additional specifications or extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is included by either passing an optional :version parameter to the validate method (set either as :draft1 or draft2), or by declaring the $schema attribute in the schema and referencing the appropriate specification URI. Note that the $schema attribute takes precedence over the :version option during parsing and validation. - -h3. Validate Ruby objects against a Ruby schema - -For further information on json schema itself refer to Understanding JSON Schema. - -
+```
+
+Usage
+-----
+
+Three base validation methods exist: `validate`, `validate!`, and
+`fully_validate`. The first returns a boolean on whether a validation attempt
+passes and the second will throw a `JSON::Schema::ValidationError` with an
+appropriate message/trace on where the validation failed. The third validation
+method does not immediately fail upon a validation error and instead builds an
+array of validation errors return when validation is complete.
+
+All methods take two arguments, which can be either a JSON string, a file
+containing JSON, or a Ruby object representing JSON data. The first argument to
+these methods is always the schema, the second is always the data to validate.
+An optional third options argument is also accepted; available options are used
+in the examples below.
+
+By default, the validator uses the [JSON Schema Draft
+4](http://tools.ietf.org/html/draft-zyp-json-schema-04) specification for
+validation; however, the user is free to specify additional specifications or
+extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is
+included by either passing an optional `:version` parameter to the `validate`
+method (set either as `:draft1` or `draft2`), or by declaring the `$schema`
+attribute in the schema and referencing the appropriate specification URI. Note
+that the `$schema` attribute takes precedence over the `:version` option during
+parsing and validation.
+
+### Validate Ruby objects against a Ruby schema
+
+For further information on json schema itself refer to Understanding
+JSON Schema.
+
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -59,32 +91,35 @@ data = {
 }
 
 JSON::Validator.validate(schema, data)
-
+``` -h3. Validate a JSON string against a JSON schema file +### Validate a JSON string against a JSON schema file -
+```rb
 require 'rubygems'
 require 'json-schema'
 
 JSON::Validator.validate('schema.json', '{"a" : 5}')
-
+``` -h3. Validate a list of objects against a schema that represents the individual objects +### Validate a list of objects against a schema that represents the individual objects -
+```rb
 require 'rubygems'
 require 'json-schema'
 
 data = ['user','user','user']
 JSON::Validator.validate('user.json', data, :list => true)
-
+``` -h3. Strictly validate an object's properties +### Strictly validate an object's properties -With the :strict option, validation fails when an object contains properties that are not defined in the schema's property list or doesn't match the additionalProperties property. Furthermore, all properties are treated as required regardless of required properties set in the schema. +With the `:strict` option, validation fails when an object contains properties +that are not defined in the schema's property list or doesn't match the +`additionalProperties` property. Furthermore, all properties are treated as +`required` regardless of `required` properties set in the schema. -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -99,11 +134,11 @@ schema = {
 JSON::Validator.validate(schema, {"a" => 1, "b" => 2}, :strict => true)            # ==> true
 JSON::Validator.validate(schema, {"a" => 1, "b" => 2, "c" => 3}, :strict => true)  # ==> false
 JSON::Validator.validate(schema, {"a" => 1}, :strict => true)                      # ==> false
-
+``` -h3. Catch a validation error and print it out +### Catch a validation error and print it out -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -124,12 +159,11 @@ begin
 rescue JSON::Schema::ValidationError
   puts $!.message
 end
-
- +``` -h3. Fully validate against a schema and catch all errors +### Fully validate against a schema and catch all errors -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -149,11 +183,11 @@ data = {
 errors = JSON::Validator.fully_validate(schema, data)
 
 # ["The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", "The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#"]
-
+``` -h3. Fully validate against a schema and catch all errors as objects +### Fully validate against a schema and catch all errors as objects -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -172,41 +206,40 @@ data = {
 
 errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true)
 
-# [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Properties", :fragment=>"#/"}]
+# [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Properties", :fragment=>"#/"}]
+```
 
-
+### Validate against a fragment of a supplied schema -h3. Validate against a fragment of a supplied schema - -
-  require 'rubygems'
-  require 'json-schema'
+```rb
+require 'rubygems'
+require 'json-schema'
 
-  schema = {
-    "type" => "object",
-    "required" => ["a","b"],
-    "properties" => {
-      "a" => {"type" => "integer"},
-      "b" => {"type" => "string"},
-      "c" => {
-        "type" => "object",
-        "properties" => {
-          "z" => {"type" => "integer"}
-        }
+schema = {
+  "type" => "object",
+  "required" => ["a","b"],
+  "properties" => {
+    "a" => {"type" => "integer"},
+    "b" => {"type" => "string"},
+    "c" => {
+      "type" => "object",
+      "properties" => {
+        "z" => {"type" => "integer"}
       }
     }
   }
+}
 
-  data = {
-    "z" => 1
-  }
+data = {
+  "z" => 1
+}
 
-  JSON::Validator.validate(schema, data, :fragment => "#/properties/c")
-
+JSON::Validator.validate(schema, data, :fragment => "#/properties/c") +``` -h3. Validate a JSON object against a JSON schema object, while also validating the schema itself +### Validate a JSON object against a JSON schema object, while also validating the schema itself -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -223,14 +256,16 @@ data = {
 }
 
 JSON::Validator.validate(schema, data, :validate_schema => true)
-
+``` -h3. Validate a JSON object against a JSON schema object, while inserting default values from the schema +### Validate a JSON object against a JSON schema object, while inserting default values from the schema -With the :insert_defaults option set to true any missing property that has a -default value specified in the schema will be inserted into the validated data. The inserted default value is validated hence catching a schema that specifies an invalid default value. +With the `:insert_defaults` option set to true any missing property that has a +default value specified in the schema will be inserted into the validated data. +The inserted default value is validated hence catching a schema that specifies +an invalid default value. -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -258,11 +293,11 @@ JSON::Validator.validate(schema, data, :insert_defaults => true)
 #   "a" => 42,
 #   "b" => 5
 # }
+```
 
-
-h3. Validate an object against a JSON Schema Draft 2 schema +### Validate an object against a JSON Schema Draft 2 schema -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -278,15 +313,23 @@ data = {
 }
 
 JSON::Validator.validate(schema, data, :version => :draft2)
-
+``` -h3. Explicitly specifying the type of the data +### Explicitly specifying the type of the data -By default, json-schema accepts a variety of different types for the data parameter, and it will try to work out what to do with it dynamically. You can pass it a string uri (in which case it will download the json from that location before validating), a string of JSON text, or simply a ruby object (such as an array or hash representing parsed json). However, sometimes the nature of the data is ambiguous (for example, is "http://github.com" just a string, or is it a uri?). In other situations, you have already parsed your JSON, and you don't need to re-parse it. +By default, json-schema accepts a variety of different types for the data +parameter, and it will try to work out what to do with it dynamically. You can +pass it a string uri (in which case it will download the json from that location +before validating), a string of JSON text, or simply a ruby object (such as an +array or hash representing parsed json). However, sometimes the nature of the +data is ambiguous (for example, is "http://github.com" just a string, or is it a +uri?). In other situations, you have already parsed your JSON, and you don't +need to re-parse it. -If you want to be explict about what kind of data is being parsed, JSON schema supports a number of options: +If you want to be explict about what kind of data is being parsed, JSON schema +supports a number of options: -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -305,13 +348,15 @@ JSON::Validator.validate(schema, '"https://api.github.com"', :json => true) # re
 
 # loads data from the uri
 JSON::Validator.validate(schema, 'https://api.github.com', :uri => true) # returns false
-
+``` -h3. Extend an existing schema and validate against it +### Extend an existing schema and validate against it -For this example, we are going to extend the "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03 specification by adding a 'bitwise-and' property for validation. +For this example, we are going to extend the [JSON Schema Draft +3](http://tools.ietf.org/html/draft-zyp-json-schema-03) specification by adding +a 'bitwise-and' property for validation. -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -357,13 +402,18 @@ data = {"a" => 1, "b" => 5}
 JSON::Validator.validate(schema,data) # => false
 data = {"a" => 0, "b" => "taco"}
 JSON::Validator.validate(schema,data) # => false
-
+``` -h3. Custom format validation +### Custom format validation -The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows registering procs as custom format validators which receive the value to be checked as parameter and must raise a JSON::Schema::CustomFormatError to indicate a format violation. The error message will be prepended by the property name, e.g. "The property '#a'": +The JSON schema standard allows custom formats in schema definitions which +should be ignored by validators that do not support them. JSON::Schema allows +registering procs as custom format validators which receive the value to be +checked as parameter and must raise a `JSON::Schema::CustomFormatError` to +indicate a format violation. The error message will be prepended by the property +name, e.g. [The property '#a']() -
+```rb
 require 'rubygems'
 require 'json-schema'
 
@@ -396,21 +446,26 @@ schema = {
   }
 }
 errors = JSON::Validator.fully_validate(schema, {"a" => "23"})
+```
 
-
+Controlling Remote Schema Reading +--------------------------------- -h2. Controlling Remote Schema Reading +In some cases, you may wish to prevent the JSON Schema library from making HTTP +calls or reading local files in order to resolve `$ref` schemas. If you fully +control all schemas which should be used by validation, this could be +accomplished by registering all referenced schemas with the validator in +advance: -In some cases, you may wish to prevent the JSON Schema library from making HTTP calls or reading local files in order to resolve $ref schemas. If you fully control all schemas which should be used by validation, this could be accomplished by registering all referenced schemas with the validator in advance: - -
+```rb
 schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema'))
 JSON::Validator.add_schema(schema)
-
+``` -If more extensive control is necessary, the JSON::Schema::Reader instance used can be configured in a few ways: +If more extensive control is necessary, the `JSON::Schema::Reader` instance used +can be configured in a few ways: -
+```rb
 # Change the default schema reader used
 JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false)
 
@@ -419,34 +474,47 @@ schema_reader = JSON::Schema::Reader.new(
   :accept_uri => proc { |uri| uri.host == 'my-website.com' }
 )
 JSON::Validator.validate(some_schema, some_object, :schema_reader => schema_reader)
-
+``` -The JSON::Schema::Reader interface requires only an object which responds to read(string) and returns a JSON::Schema instance. See the "API documentation":http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader for more information. +The `JSON::Schema::Reader` interface requires only an object which responds to +`read(string)` and returns a `JSON::Schema` instance. See the [API +documentation](http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader) +for more information. -h2. JSON Backends +JSON Backends +------------- -The JSON Schema library currently supports the json and yajl-ruby backend JSON parsers. If either of these libraries are installed, they will be automatically loaded and used to parse any JSON strings supplied by the user. +The JSON Schema library currently supports the `json` and `yajl-ruby` backend +JSON parsers. If either of these libraries are installed, they will be +automatically loaded and used to parse any JSON strings supplied by the user. -If more than one of the supported JSON backends are installed, the yajl-ruby parser is used by default. This can be changed by issuing the following before validation: +If more than one of the supported JSON backends are installed, the `yajl-ruby` +parser is used by default. This can be changed by issuing the following before +validation: -
+```rb
 JSON::Validator.json_backend = :json
-
+``` -Optionally, the JSON Schema library supports using the MultiJSON library for selecting JSON backends. If the MultiJSON library is installed, it will be autoloaded. +Optionally, the JSON Schema library supports using the MultiJSON library for +selecting JSON backends. If the MultiJSON library is installed, it will be +autoloaded. -h2. Notes +Notes +----- The 'format' attribute is only validated for the following values: -* date-time -* date -* time -* ip-address (IPv4 address in draft1, draft2 and draft3) -* ipv4 (IPv4 address in draft4) -* ipv6 -* uri - -All other 'format' attribute values are simply checked to ensure the instance value is of the correct datatype (e.g., an instance value is validated to be an integer or a float in the case of 'utc-millisec'). +- date-time +- date +- time +- ip-address (IPv4 address in draft1, draft2 and draft3) +- ipv4 (IPv4 address in draft4) +- ipv6 +- uri + +All other 'format' attribute values are simply checked to ensure the instance +value is of the correct datatype (e.g., an instance value is validated to be an +integer or a float in the case of 'utc-millisec'). Additionally, JSON::Validator does not handle any json hyperschema attributes. diff --git a/json-schema.gemspec b/json-schema.gemspec index 4c144529..0a6a69b4 100644 --- a/json-schema.gemspec +++ b/json-schema.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |s| s.summary = "Ruby JSON Schema Validator" s.files = Dir[ "lib/**/*", "resources/*.json" ] s.require_path = "lib" - s.extra_rdoc_files = ["README.textile","LICENSE.md"] + s.extra_rdoc_files = ["README.md","LICENSE.md"] s.required_ruby_version = ">= 1.8.7" s.license = "MIT" s.required_rubygems_version = ">= 1.8" From f7b542ed8bfdd553ef19f70d000a9e9008c9da57 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 17 Feb 2016 16:34:10 +0000 Subject: [PATCH 30/43] Added the readme change to CHANGELING.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa818ae0..3c6487f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Made sure schemas of an unrecognized type raise a SchemaParseError (not Name error) +### Changed +- Readme was converted from textile to markdown + ## [2.6.0] - 2016-01-08 ### Added From 5d57af4b346367f97ca2f290d5c9aa2eb35f27fe Mon Sep 17 00:00:00 2001 From: Scott Kobewka Date: Wed, 17 Feb 2016 16:27:57 -0500 Subject: [PATCH 31/43] Update README.md Making it a little easier to read the descriptions of the three validate methods. --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f14fe25a..64319d91 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,11 @@ $ gem install json-schema-2.5.2.gem Usage ----- -Three base validation methods exist: `validate`, `validate!`, and -`fully_validate`. The first returns a boolean on whether a validation attempt -passes and the second will throw a `JSON::Schema::ValidationError` with an -appropriate message/trace on where the validation failed. The third validation -method does not immediately fail upon a validation error and instead builds an -array of validation errors return when validation is complete. +Three base validation methods exist: + +1. `validate`: returns a boolean on whether a validation attempt passes +2. `validate!`: throws a `JSON::Schema::ValidationError` with an appropriate message/trace on where the validation failed +3. `fully_validate`: builds an array of validation errors return when validation is complete All methods take two arguments, which can be either a JSON string, a file containing JSON, or a Ruby object representing JSON data. The first argument to From 2ab0331a1b2009e23f7bd1b7206b8c64189f7f4b Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 26 Feb 2016 09:52:05 +0000 Subject: [PATCH 32/43] Bumped version to 2.6.1 --- CHANGELOG.md | 2 ++ VERSION.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6487f5..7affbf08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [2.6.1] - 2016-02-26 + ### Fixed - Made sure schemas of an unrecognized type raise a SchemaParseError (not Name error) diff --git a/VERSION.yml b/VERSION.yml index e9a7eddb..fdff4d8b 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,3 +1,3 @@ major: 2 minor: 6 -patch: 0 +patch: 1 From 354490f500d2e2567777e4383895b86bc136da9b Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 26 Feb 2016 10:02:40 +0000 Subject: [PATCH 33/43] Corrected build status links in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 64319d91..8c3f2592 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -![https://travis-ci.org/ruby-json-schema/json-schema](https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master) -![https://codeclimate.com/github/ruby-json-schema/json-schema](https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg) +[![Travis](https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master)](https://travis-ci.org/ruby-json-schema/json-schema) +[![Code Climate](https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg)](https://codeclimate.com/github/ruby-json-schema/json-schema) Ruby JSON Schema Validator ========================== From 33b2b05e6cf9235e303f474ca1db962ca670928d Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 18 Mar 2016 12:31:31 +0000 Subject: [PATCH 34/43] Reformatted the examples to make them easier to read --- CHANGELOG.md | 3 + README.md | 399 ++++++++++++++++++++------------------------------- 2 files changed, 157 insertions(+), 245 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7affbf08..f77c4264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed +- Reformatted examples in the readme + ## [2.6.1] - 2016-02-26 ### Fixed diff --git a/README.md b/README.md index 8c3f2592..b32fafa6 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ $ gem build json-schema.gemspec $ gem install json-schema-2.5.2.gem ``` -Usage +Validation ----- -Three base validation methods exist: +Three base validation methods exist: 1. `validate`: returns a boolean on whether a validation attempt passes 2. `validate!`: throws a `JSON::Schema::ValidationError` with an appropriate message/trace on where the validation failed @@ -67,15 +67,15 @@ attribute in the schema and referencing the appropriate specification URI. Note that the `$schema` attribute takes precedence over the `:version` option during parsing and validation. -### Validate Ruby objects against a Ruby schema - For further information on json schema itself refer to Understanding JSON Schema. -```rb -require 'rubygems' -require 'json-schema' +Basic Usage +-------------- + +```ruby +require "json-schema" schema = { "type" => "object", @@ -85,279 +85,188 @@ schema = { } } -data = { - "a" => 5 -} - -JSON::Validator.validate(schema, data) -``` - -### Validate a JSON string against a JSON schema file +# +# validate ruby objects against a ruby schema +# -```rb -require 'rubygems' -require 'json-schema' +# => true +JSON::Validator.validate(schema, { "a" => 5 }) +# => false +JSON::Validator.validate(schema, {}) -JSON::Validator.validate('schema.json', '{"a" : 5}') -``` +# +# validate a json string against a json schema file +# -### Validate a list of objects against a schema that represents the individual objects +require "json" +File.write("schema.json", JSON.dump(schema)) -```rb -require 'rubygems' -require 'json-schema' - -data = ['user','user','user'] -JSON::Validator.validate('user.json', data, :list => true) -``` - -### Strictly validate an object's properties - -With the `:strict` option, validation fails when an object contains properties -that are not defined in the schema's property list or doesn't match the -`additionalProperties` property. Furthermore, all properties are treated as -`required` regardless of `required` properties set in the schema. - -```rb -require 'rubygems' -require 'json-schema' - -schema = { - "type" => "object", - "properties" => { - "a" => {"type" => "integer"}, - "b" => {"type" => "integer"} - } -} - -JSON::Validator.validate(schema, {"a" => 1, "b" => 2}, :strict => true) # ==> true -JSON::Validator.validate(schema, {"a" => 1, "b" => 2, "c" => 3}, :strict => true) # ==> false -JSON::Validator.validate(schema, {"a" => 1}, :strict => true) # ==> false -``` - -### Catch a validation error and print it out - -```rb -require 'rubygems' -require 'json-schema' - -schema = { - "type" => "object", - "required" => ["a"], - "properties" => { - "a" => {"type" => "integer"} - } -} +# => true +JSON::Validator.validate('schema.json', '{ "a": 5 }') -data = { - "a" => "taco" -} +# +# raise an error when validation fails +# +# => "The property '#/a' of type String did not match the following type: integer" begin - JSON::Validator.validate!(schema, data) -rescue JSON::Schema::ValidationError - puts $!.message + JSON::Validator.validate!(schema, { "a" => "taco" }) +rescue JSON::Schema::ValidationError => e + e.message end -``` - -### Fully validate against a schema and catch all errors - -```rb -require 'rubygems' -require 'json-schema' - -schema = { - "type" => "object", - "required" => ["a","b"], - "properties" => { - "a" => {"type" => "integer"}, - "b" => {"type" => "string"} - } -} - -data = { - "a" => "taco" -} - -errors = JSON::Validator.fully_validate(schema, data) - -# ["The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", "The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#"] -``` - -### Fully validate against a schema and catch all errors as objects - -```rb -require 'rubygems' -require 'json-schema' - -schema = { - "type" => "object", - "required" => ["a","b"], - "properties" => { - "a" => {"type" => "integer"}, - "b" => {"type" => "string"} - } -} - -data = { - "a" => "taco" -} -errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true) +# +# return an array of error messages when validation fails +# -# [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Properties", :fragment=>"#/"}] +# => ["The property '#/a' of type String did not match the following type: integer in schema 18a1ffbb-4681-5b00-bd15-2c76aee4b28f"] +JSON::Validator.fully_validate(schema, { "a" => "taco" }) ``` -### Validate against a fragment of a supplied schema +Advanced Options +----------------- -```rb -require 'rubygems' -require 'json-schema' +```ruby +require "json-schema" schema = { - "type" => "object", - "required" => ["a","b"], + "type"=>"object", + "required" => ["a"], "properties" => { - "a" => {"type" => "integer"}, - "b" => {"type" => "string"}, - "c" => { + "a" => { + "type" => "integer", + "default" => 42 + }, + "b" => { "type" => "object", "properties" => { - "z" => {"type" => "integer"} + "x" => { + "type" => "integer" + } } } } } -data = { - "z" => 1 -} - -JSON::Validator.validate(schema, data, :fragment => "#/properties/c") -``` - -### Validate a JSON object against a JSON schema object, while also validating the schema itself - -```rb -require 'rubygems' -require 'json-schema' - -schema = { - "type" => "object", - "required" => ["a"], - "properties" => { - "a" => {"type" => "integer", "required" => "true"} # This will fail schema validation! - } -} - -data = { - "a" => 5 -} - -JSON::Validator.validate(schema, data, :validate_schema => true) -``` - -### Validate a JSON object against a JSON schema object, while inserting default values from the schema - -With the `:insert_defaults` option set to true any missing property that has a -default value specified in the schema will be inserted into the validated data. -The inserted default value is validated hence catching a schema that specifies -an invalid default value. - -```rb -require 'rubygems' -require 'json-schema' - -schema = { - "type" => "object", - "required" => ["a"], - "properties" => { - "a" => {"type" => "integer", "default" => 42}, - "b" => {"type" => "integer"} - } -} - -# Would not normally validate because "a" is missing and required by schema, -# but "default" option allows insertion of valid default. -data = { - "b" => 5 -} - -JSON::Validator.validate(schema, data) -# false - -JSON::Validator.validate(schema, data, :insert_defaults => true) -# true -# data = { -# "a" => 42, -# "b" => 5 -# } -``` - -### Validate an object against a JSON Schema Draft 2 schema - -```rb -require 'rubygems' -require 'json-schema' - -schema = { +# +# with the `:list` option, a list can be validated against a schema that represents the individual objects +# + +# => true +JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}], :list => true) +# => false +JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}]) + +# +# with the `:errors_as_objects` option, `#fully_validate` returns errors as hashes instead of strings +# + +# => [{:schema=>#, :fragment=>"#/a", :message=>"The property '#/a' of type String did not match the following type: integer in schema 18a1ffbb-4681-5b00-bd15-2c76aee4b28f", :failed_attribute=>"TypeV4"}] +JSON::Validator.fully_validate(schema, { "a" => "taco" }, :errors_as_objects => true) + +# +# with the `:strict` option, all properties are condisidered to have `"required": true` and all objects `"additionalProperties": false` +# + +# => true +JSON::Validator.validate(schema, { "a" => 1, "b" => { "x" => 2 } }, :strict => true) +# => false +JSON::Validator.validate(schema, { "a" => 1, "b" => { "x" => 2 }, "c" => 3 }, :strict => true) +# => false +JSON::Validator.validate(schema, { "a" => 1 }, :strict => true) + +# +# with the `:fragment` option, only a fragment of the schema is used for validation +# + +# => true +JSON::Validator.validate(schema, { "x" => 1 }, :fragment => "#/properties/b") +# => false +JSON::Validator.validate(schema, { "x" => 1 }) + +# +# with the `:validate_schema` option, the schema is validated (against the json schema spec) before the json is validated (against the specified schema) +# + +# => true +JSON::Validator.validate(schema, { "a" => 1 }, :validate_schema => true) +# => false +JSON::Validator.validate({ "required" => true }, { "a" => 1 }, :validate_schema => true) + +# +# with the `:insert_defaults` option, any undefined values in the json that have a default in the schema are replaced with the default before validation +# + +# => true +JSON::Validator.validate(schema, {}, :insert_defaults => true) +# => false +JSON::Validator.validate(schema, {}) + +# +# with the `:version` option, schemas conforming to older drafts of the json schema spec can be used +# + +v2_schema = { "type" => "object", "properties" => { - "a" => {"type" => "integer", "optional" => true} + "a" => { + "type" => "integer" + } } } -data = { - "a" => 5 -} - -JSON::Validator.validate(schema, data, :version => :draft2) -``` - -### Explicitly specifying the type of the data +# => false +JSON::Validator.validate(v2_schema, {}, :version => :draft2) +# => true +JSON::Validator.validate(v2_schema, {}) -By default, json-schema accepts a variety of different types for the data -parameter, and it will try to work out what to do with it dynamically. You can -pass it a string uri (in which case it will download the json from that location -before validating), a string of JSON text, or simply a ruby object (such as an -array or hash representing parsed json). However, sometimes the nature of the -data is ambiguous (for example, is "http://github.com" just a string, or is it a -uri?). In other situations, you have already parsed your JSON, and you don't -need to re-parse it. +# +# with the `:parse_data` option set to false, the json must be a parsed ruby object (not a json text, a uri or a file path) +# -If you want to be explict about what kind of data is being parsed, JSON schema -supports a number of options: +# => true +JSON::Validator.validate(schema, { "a" => 1 }, :parse_data => false) +# => false +JSON::Validator.validate(schema, '{ "a": 1 }', :parse_data => false) -```rb -require 'rubygems' -require 'json-schema' +# +# with the `:json` option, the json must be an unparsed json text (not a hash, a uri or a file path) +# -schema = { - "type" => "string" -} - -# examines the data, determines it's a uri, then tries to load data from it -JSON::Validator.validate(schema, 'https://api.github.com') # returns false +# => true +JSON::Validator.validate(schema, '{ "a": 1 }', :json => true) +# => "no implicit conversion of Hash into String" +begin + JSON::Validator.validate(schema, { "a" => 1 }, :json => true) +rescue TypeError => e + e.message +end -# data is already parsed json - just accept it as-is -JSON::Validator.validate(schema, 'https://api.github.com', :parse_data => false) # returns true +# +# with the `:uri` option, the json must be a uri or file path (not a hash or a json text) +# -# data is parsed to a json string -JSON::Validator.validate(schema, '"https://api.github.com"', :json => true) # returns true +File.write("data.json", '{ "a": 1 }') -# loads data from the uri -JSON::Validator.validate(schema, 'https://api.github.com', :uri => true) # returns false +# => true +JSON::Validator.validate(schema, "data.json", :uri => true) +# => "Can't convert Hash into String." +begin + JSON::Validator.validate(schema, { "a" => 1 }, :uri => true) +rescue TypeError => e + e.message +end ``` -### Extend an existing schema and validate against it +Extending Schemas +----------------- For this example, we are going to extend the [JSON Schema Draft 3](http://tools.ietf.org/html/draft-zyp-json-schema-03) specification by adding a 'bitwise-and' property for validation. -```rb -require 'rubygems' -require 'json-schema' +```ruby +require "json-schema" class BitwiseAndAttribute < JSON::Schema::Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) @@ -403,7 +312,8 @@ data = {"a" => 0, "b" => "taco"} JSON::Validator.validate(schema,data) # => false ``` -### Custom format validation +Custom format validation +------------------------ The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows @@ -412,9 +322,8 @@ checked as parameter and must raise a `JSON::Schema::CustomFormatError` to indicate a format violation. The error message will be prepended by the property name, e.g. [The property '#a']() -```rb -require 'rubygems' -require 'json-schema' +```ruby +require "json-schema" format_proc = -> value { raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" @@ -456,7 +365,7 @@ control all schemas which should be used by validation, this could be accomplished by registering all referenced schemas with the validator in advance: -```rb +```ruby schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema')) JSON::Validator.add_schema(schema) ``` @@ -464,7 +373,7 @@ JSON::Validator.add_schema(schema) If more extensive control is necessary, the `JSON::Schema::Reader` instance used can be configured in a few ways: -```rb +```ruby # Change the default schema reader used JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false) @@ -491,7 +400,7 @@ If more than one of the supported JSON backends are installed, the `yajl-ruby` parser is used by default. This can be changed by issuing the following before validation: -```rb +```ruby JSON::Validator.json_backend = :json ``` From b2e4fdef000e4f012036f7e8d36601e73de18dcc Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 15 Apr 2016 16:40:23 +0100 Subject: [PATCH 35/43] Made it possible to have refs that include URI-special characters Turns out that before: * if you had a ref that included a colon, the text before the colon was treated as the scheme and the text after the colon as a path * the unescape_uri method was actually only parsing the path of the uri (therefore anything before a colon was being stripped when passed to unescape_uri) Fixes #319 --- CHANGELOG.md | 3 +++ lib/json-schema/attributes/ref.rb | 4 ++-- lib/json-schema/schema/reader.rb | 2 +- lib/json-schema/util/uri.rb | 6 +++++- lib/json-schema/validator.rb | 2 +- .../definition_schema_with_special_characters.json | 14 ++++++++++++++ test/test_definition.rb | 4 ++++ 7 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 test/schemas/definition_schema_with_special_characters.json diff --git a/CHANGELOG.md b/CHANGELOG.md index f77c4264..0cc8bdfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +- Made it possible to include colons in a $ref + ### Changed - Reformatted examples in the readme diff --git a/lib/json-schema/attributes/ref.rb b/lib/json-schema/attributes/ref.rb index 508f7340..2db8b2f5 100644 --- a/lib/json-schema/attributes/ref.rb +++ b/lib/json-schema/attributes/ref.rb @@ -48,11 +48,11 @@ def self.get_referenced_uri_and_schema(s, current_schema, validator) if ref_schema # Perform fragment resolution to retrieve the appropriate level for the schema target_schema = ref_schema.schema - fragments = temp_uri.fragment.split("/") + fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split("/") fragment_path = '' fragments.each do |fragment| if fragment && fragment != '' - fragment = JSON::Util::URI.unescaped_uri(fragment.gsub('~0', '~').gsub('~1', '/')) + fragment = fragment.gsub('~0', '~').gsub('~1', '/') if target_schema.is_a?(Array) target_schema = target_schema[fragment.to_i] else diff --git a/lib/json-schema/schema/reader.rb b/lib/json-schema/schema/reader.rb index ae7bdf41..1493d1f0 100644 --- a/lib/json-schema/schema/reader.rb +++ b/lib/json-schema/schema/reader.rb @@ -102,7 +102,7 @@ def read_uri(uri) def read_file(pathname) if accept_file?(pathname) - File.read(JSON::Util::URI.unescaped_uri(pathname.to_s)) + File.read(JSON::Util::URI.unescaped_path(pathname.to_s)) else raise JSON::Schema::ReadRefused.new(pathname.to_s, :file) end diff --git a/lib/json-schema/util/uri.rb b/lib/json-schema/util/uri.rb index 4ddf2ea7..6061625e 100644 --- a/lib/json-schema/util/uri.rb +++ b/lib/json-schema/util/uri.rb @@ -54,7 +54,11 @@ def self.file_uri(uri) Addressable::URI.convert_path(parsed_uri.path) end - def self.unescaped_uri(uri) + def self.unescape_uri(uri) + Addressable::URI.unescape(uri) + end + + def self.unescaped_path(uri) parsed_uri = parse(uri) Addressable::URI.unescape(parsed_uri.path) diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 50b5b07f..9b947ff8 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -608,7 +608,7 @@ def custom_open(uri) end else begin - File.read(JSON::Util::URI.unescaped_uri(uri)) + File.read(JSON::Util::URI.unescaped_path(uri)) rescue SystemCallError => e raise JSON::Schema::JsonLoadError, e.message end diff --git a/test/schemas/definition_schema_with_special_characters.json b/test/schemas/definition_schema_with_special_characters.json new file mode 100644 index 00000000..d6ac2338 --- /dev/null +++ b/test/schemas/definition_schema_with_special_characters.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "a": { + "$ref": "#/definitions/foo:bar" + } + }, + "definitions": { + "foo:bar": { + "type": "integer" + } + } +} diff --git a/test/test_definition.rb b/test/test_definition.rb index 42541204..cc020074 100644 --- a/test/test_definition.rb +++ b/test/test_definition.rb @@ -6,6 +6,10 @@ def test_definition_schema assert_valid schema_fixture_path('definition_schema.json'), {"a" => 5} end + def test_definition_schema_with_special_characters + assert_valid schema_fixture_path('definition_schema_with_special_characters.json'), {"a" => 5} + end + def test_relative_definition schema = schema_fixture_path('relative_definition_schema.json') assert_valid schema, {"a" => 5} From 96b10fc8e56520e4812068d133818cd652973b7e Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 13 May 2016 15:38:34 +0100 Subject: [PATCH 36/43] Bumped version to 2.6.2 --- CHANGELOG.md | 2 ++ VERSION.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cc8bdfe..3610dc7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [2.6.2] - 2016-05-13 + ### Fixed - Made it possible to include colons in a $ref diff --git a/VERSION.yml b/VERSION.yml index fdff4d8b..6f1b0691 100644 --- a/VERSION.yml +++ b/VERSION.yml @@ -1,3 +1,3 @@ major: 2 minor: 6 -patch: 1 +patch: 2 From 0e279d9c570d27c9e4c006b5e0be9ee103c30af6 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 22 Jun 2016 14:19:46 +0100 Subject: [PATCH 37/43] Updated common test suite --- test/test-suite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-suite b/test/test-suite index 9723c8f2..2f0d6e36 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 9723c8f2f5f7c471c5147d5d6d08f4aa10a89f83 +Subproject commit 2f0d6e3686b0989665b05c4a0b147ea6ce357198 From d9661403a9084978ed21fadbaf411db1077c2d0b Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 8 Jan 2016 11:59:05 +0000 Subject: [PATCH 38/43] Made sure test filenames match class names --- Rakefile | 2 +- ...ef_schema.rb => all_of_ref_schema_test.rb} | 0 ...ef_schema.rb => any_of_ref_schema_test.rb} | 0 ...d_schema_ref.rb => bad_schema_ref_test.rb} | 0 ...est_suite.rb => common_test_suite_test.rb} | 0 ...custom_format.rb => custom_format_test.rb} | 4 +- ...st_jsonschema_draft1.rb => draft1_test.rb} | 3 +- ...st_jsonschema_draft2.rb => draft2_test.rb} | 3 +- ...st_jsonschema_draft3.rb => draft3_test.rb} | 3 +- ...st_jsonschema_draft4.rb => draft4_test.rb} | 4 +- ...nded_schema.rb => extended_schema_test.rb} | 2 +- ...alProperties.rb => extends_nested_test.rb} | 0 test/{test_files_v3.rb => files_test.rb} | 26 +++++++---- ...olution.rb => fragment_resolution_test.rb} | 2 +- ...b => fragment_validation_with_ref_test.rb} | 2 +- ..._validation.rb => full_validation_test.rb} | 46 +++++++++---------- ...ialize_data.rb => initialize_data_test.rb} | 0 ...est_list_option.rb => list_option_test.rb} | 0 ..._ref_schema.rb => load_ref_schema_test.rb} | 2 +- ...values.rb => merge_missing_values_test.rb} | 0 test/{test_minitems.rb => min_items_test.rb} | 0 test/{test_one_of.rb => one_of_test.rb} | 0 ...inition.rb => relative_definition_test.rb} | 0 ...est_ruby_schema.rb => ruby_schema_test.rb} | 0 ...schema_loader.rb => schema_reader_test.rb} | 2 +- ...alidation.rb => schema_validation_test.rb} | 2 +- test/{test_stringify.rb => stringify_test.rb} | 0 ...pe_attribute.rb => type_attribute_test.rb} | 2 +- ...est_uri_related.rb => uri_parsing_test.rb} | 2 +- ...tor.rb => validator_schema_reader_test.rb} | 2 +- 30 files changed, 56 insertions(+), 53 deletions(-) rename test/{test_all_of_ref_schema.rb => all_of_ref_schema_test.rb} (100%) rename test/{test_any_of_ref_schema.rb => any_of_ref_schema_test.rb} (100%) rename test/{test_bad_schema_ref.rb => bad_schema_ref_test.rb} (100%) rename test/{test_common_test_suite.rb => common_test_suite_test.rb} (100%) rename test/{test_custom_format.rb => custom_format_test.rb} (99%) rename test/{test_jsonschema_draft1.rb => draft1_test.rb} (98%) rename test/{test_jsonschema_draft2.rb => draft2_test.rb} (98%) rename test/{test_jsonschema_draft3.rb => draft3_test.rb} (99%) rename test/{test_jsonschema_draft4.rb => draft4_test.rb} (99%) rename test/{test_extended_schema.rb => extended_schema_test.rb} (97%) rename test/{test_extends_and_additionalProperties.rb => extends_nested_test.rb} (100%) rename test/{test_files_v3.rb => files_test.rb} (57%) rename test/{test_fragment_resolution.rb => fragment_resolution_test.rb} (94%) rename test/{test_fragment_validation_with_ref.rb => fragment_validation_with_ref_test.rb} (93%) rename test/{test_full_validation.rb => full_validation_test.rb} (97%) rename test/{test_initialize_data.rb => initialize_data_test.rb} (100%) rename test/{test_list_option.rb => list_option_test.rb} (100%) rename test/{test_load_ref_schema.rb => load_ref_schema_test.rb} (95%) rename test/{test_merge_missing_values.rb => merge_missing_values_test.rb} (100%) rename test/{test_minitems.rb => min_items_test.rb} (100%) rename test/{test_one_of.rb => one_of_test.rb} (100%) rename test/{test_definition.rb => relative_definition_test.rb} (100%) rename test/{test_ruby_schema.rb => ruby_schema_test.rb} (100%) rename test/{test_schema_loader.rb => schema_reader_test.rb} (98%) rename test/{test_schema_validation.rb => schema_validation_test.rb} (99%) rename test/{test_stringify.rb => stringify_test.rb} (100%) rename test/{test_schema_type_attribute.rb => type_attribute_test.rb} (92%) rename test/{test_uri_related.rb => uri_parsing_test.rb} (97%) rename test/{test_validator.rb => validator_schema_reader_test.rb} (96%) diff --git a/Rakefile b/Rakefile index 76591dd9..1e28f7f3 100644 --- a/Rakefile +++ b/Rakefile @@ -16,7 +16,7 @@ Rake::TestTask.new do |t| t.libs << "." t.warning = true t.verbose = true - t.test_files = FileList.new('test/test*.rb') do |fl| + t.test_files = FileList.new('test/*_test.rb') do |fl| fl.exclude(/test_helper\.rb$/) end end diff --git a/test/test_all_of_ref_schema.rb b/test/all_of_ref_schema_test.rb similarity index 100% rename from test/test_all_of_ref_schema.rb rename to test/all_of_ref_schema_test.rb diff --git a/test/test_any_of_ref_schema.rb b/test/any_of_ref_schema_test.rb similarity index 100% rename from test/test_any_of_ref_schema.rb rename to test/any_of_ref_schema_test.rb diff --git a/test/test_bad_schema_ref.rb b/test/bad_schema_ref_test.rb similarity index 100% rename from test/test_bad_schema_ref.rb rename to test/bad_schema_ref_test.rb diff --git a/test/test_common_test_suite.rb b/test/common_test_suite_test.rb similarity index 100% rename from test/test_common_test_suite.rb rename to test/common_test_suite_test.rb diff --git a/test/test_custom_format.rb b/test/custom_format_test.rb similarity index 99% rename from test/test_custom_format.rb rename to test/custom_format_test.rb index 794383e5..4d07e427 100644 --- a/test/test_custom_format.rb +++ b/test/custom_format_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require File.expand_path('../test_helper', __FILE__) -class JSONSchemaCustomFormatTest < Minitest::Test +class CustomFormatTest < Minitest::Test def setup @all_versions = ['draft1', 'draft2', 'draft3', 'draft4', nil] @format_proc = lambda { |value| raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" } @@ -115,5 +115,3 @@ def test_override_default_format end end end - - diff --git a/test/test_jsonschema_draft1.rb b/test/draft1_test.rb similarity index 98% rename from test/test_jsonschema_draft1.rb rename to test/draft1_test.rb index 06c8298e..1779392d 100644 --- a/test/test_jsonschema_draft1.rb +++ b/test/draft1_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class JSONSchemaDraft1Test < Minitest::Test +class Draft1Test < Minitest::Test def schema_version :draft1 end @@ -138,4 +138,3 @@ def test_format_datetime end end - diff --git a/test/test_jsonschema_draft2.rb b/test/draft2_test.rb similarity index 98% rename from test/test_jsonschema_draft2.rb rename to test/draft2_test.rb index 6b4c25c2..65010411 100644 --- a/test/test_jsonschema_draft2.rb +++ b/test/draft2_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class JSONSchemaDraft2Test < Minitest::Test +class Draft2Test < Minitest::Test def schema_version :draft2 end @@ -110,4 +110,3 @@ def test_format_datetime end end - diff --git a/test/test_jsonschema_draft3.rb b/test/draft3_test.rb similarity index 99% rename from test/test_jsonschema_draft3.rb rename to test/draft3_test.rb index 1c9cae7b..e46fab3b 100644 --- a/test/test_jsonschema_draft3.rb +++ b/test/draft3_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require File.expand_path('../test_helper', __FILE__) -class JSONSchemaDraft3Test < Minitest::Test +class Draft3Test < Minitest::Test def schema_version :draft3 end @@ -447,4 +447,3 @@ def test_default end - diff --git a/test/test_jsonschema_draft4.rb b/test/draft4_test.rb similarity index 99% rename from test/test_jsonschema_draft4.rb rename to test/draft4_test.rb index 8ddb7e10..14378f79 100644 --- a/test/test_jsonschema_draft4.rb +++ b/test/draft4_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require File.expand_path('../test_helper', __FILE__) -class JSONSchemaDraft4Test < Minitest::Test +class Draft4Test < Minitest::Test def schema_version :draft4 end @@ -671,5 +671,3 @@ def test_definitions refute_valid schema, data end end - - diff --git a/test/test_extended_schema.rb b/test/extended_schema_test.rb similarity index 97% rename from test/test_extended_schema.rb rename to test/extended_schema_test.rb index b7023860..fe8ea74d 100644 --- a/test/test_extended_schema.rb +++ b/test/extended_schema_test.rb @@ -22,7 +22,7 @@ def initialize JSON::Validator.register_validator(self.new) end -class TestExtendedSchema < Minitest::Test +class ExtendedSchemaTest < Minitest::Test def test_extended_schema_validation schema = { "$schema" => "http://test.com/test.json", diff --git a/test/test_extends_and_additionalProperties.rb b/test/extends_nested_test.rb similarity index 100% rename from test/test_extends_and_additionalProperties.rb rename to test/extends_nested_test.rb diff --git a/test/test_files_v3.rb b/test/files_test.rb similarity index 57% rename from test/test_files_v3.rb rename to test/files_test.rb index d85d970c..2d3aa7da 100644 --- a/test/test_files_v3.rb +++ b/test/files_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class JSONSchemaTest < Minitest::Test +class FilesTest < Minitest::Test # # These tests are ONLY run if there is an appropriate JSON backend parser available @@ -11,18 +11,28 @@ def test_schema_from_file refute_valid schema_fixture_path('good_schema_1.json'), { "a" => "bad" } end - def test_data_from_file + def test_data_from_file_v3 schema = {"$schema" => "http://json-schema.org/draft-03/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}} assert_valid schema, data_fixture_path('good_data_1.json'), :uri => true refute_valid schema, data_fixture_path('bad_data_1.json'), :uri => true end - def test_data_from_json - if JSON::Validator.json_backend != nil - schema = {"$schema" => "http://json-schema.org/draft-03/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}} - assert_valid schema, %Q({"a": 5}), :json => true - refute_valid schema, %Q({"a": "poop"}), :json => true - end + def test_data_from_json_v3 + schema = {"$schema" => "http://json-schema.org/draft-03/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}} + assert_valid schema, %Q({"a": 5}), :json => true + refute_valid schema, %Q({"a": "poop"}), :json => true + end + + def test_data_from_file_v4 + schema = {"$schema" => "http://json-schema.org/draft-04/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}} + assert_valid schema, data_fixture_path('good_data_1.json'), :uri => true + refute_valid schema, data_fixture_path('bad_data_1.json'), :uri => true + end + + def test_data_from_json_v4 + schema = {"$schema" => "http://json-schema.org/draft-04/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}} + assert_valid schema, %Q({"a": 5}), :json => true + refute_valid schema, %Q({"a": "poop"}), :json => true end def test_both_from_file diff --git a/test/test_fragment_resolution.rb b/test/fragment_resolution_test.rb similarity index 94% rename from test/test_fragment_resolution.rb rename to test/fragment_resolution_test.rb index 95985c40..819e97b8 100644 --- a/test/test_fragment_resolution.rb +++ b/test/fragment_resolution_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class FragmentResolution < Minitest::Test +class FragmentResolutionTest < Minitest::Test def test_fragment_resolution schema = { "$schema" => "http://json-schema.org/draft-04/schema#", diff --git a/test/test_fragment_validation_with_ref.rb b/test/fragment_validation_with_ref_test.rb similarity index 93% rename from test/test_fragment_validation_with_ref.rb rename to test/fragment_validation_with_ref_test.rb index 459c541c..9a92d58d 100644 --- a/test/test_fragment_validation_with_ref.rb +++ b/test/fragment_validation_with_ref_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class FragmentValidationWithRef < Minitest::Test +class FragmentValidationWithRefTest < Minitest::Test def whole_schema { "$schema" => "http://json-schema.org/draft-04/schema#", diff --git a/test/test_full_validation.rb b/test/full_validation_test.rb similarity index 97% rename from test/test_full_validation.rb rename to test/full_validation_test.rb index 4fe470a5..aa671a0c 100644 --- a/test/test_full_validation.rb +++ b/test/full_validation_test.rb @@ -1,7 +1,7 @@ require File.expand_path('../test_helper', __FILE__) -class JSONFullValidation < Minitest::Test - +class FullValidationTest < Minitest::Test + def test_full_validation data = {"b" => {"a" => 5}} schema = { @@ -13,7 +13,7 @@ def test_full_validation } } } - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) @@ -34,7 +34,7 @@ def test_full_validation errors = JSON::Validator.fully_validate(schema,data) assert(errors.length == 2) end - + def test_full_validation_with_union_types data = {"b" => 5} schema = { @@ -46,10 +46,10 @@ def test_full_validation_with_union_types } } } - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) - + schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", @@ -59,15 +59,15 @@ def test_full_validation_with_union_types } } } - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) - + data = {"b" => "a string"} - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.length == 1) - + schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", @@ -90,24 +90,24 @@ def test_full_validation_with_union_types } } } - + data = {"b" => {"c" => "taco"}} - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) - + data = {"b" => {"d" => 6}} - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) - + data = {"b" => {"c" => 6, "d" => "OH GOD"}} - + errors = JSON::Validator.fully_validate(schema,data) assert(errors.length == 1) end - - + + def test_full_validation_with_object_errors data = {"b" => {"a" => 5}} schema = { @@ -119,7 +119,7 @@ def test_full_validation_with_object_errors } } } - + errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert(errors.empty?) @@ -144,7 +144,7 @@ def test_full_validation_with_object_errors assert(errors[1][:failed_attribute] == "Type") assert(errors[1][:fragment] == "#/c") end - + def test_full_validation_with_nested_required_properties schema = { "$schema" => "http://json-schema.org/draft-03/schema#", @@ -164,7 +164,7 @@ def test_full_validation_with_nested_required_properties } } data = {"x" => {"a"=>5, "d"=>5, "e"=>"what?"}} - + errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert_equal 2, errors.length assert_equal '#/x', errors[0][:fragment] @@ -172,7 +172,7 @@ def test_full_validation_with_nested_required_properties assert_equal '#/x/e', errors[1][:fragment] assert_equal 'Type', errors[1][:failed_attribute] end - + def test_full_validation_with_nested_required_propertiesin_array schema = { "$schema" => "http://json-schema.org/draft-03/schema#", @@ -197,7 +197,7 @@ def test_full_validation_with_nested_required_propertiesin_array missing_b= {"a"=>5} e_is_wrong_type= {"a"=>5,"b"=>5,"e"=>"what?"} data = {"x" => [missing_b, e_is_wrong_type]} - + errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert_equal 2, errors.length assert_equal '#/x/0', errors[0][:fragment] diff --git a/test/test_initialize_data.rb b/test/initialize_data_test.rb similarity index 100% rename from test/test_initialize_data.rb rename to test/initialize_data_test.rb diff --git a/test/test_list_option.rb b/test/list_option_test.rb similarity index 100% rename from test/test_list_option.rb rename to test/list_option_test.rb diff --git a/test/test_load_ref_schema.rb b/test/load_ref_schema_test.rb similarity index 95% rename from test/test_load_ref_schema.rb rename to test/load_ref_schema_test.rb index 9af9a7a1..2f350732 100644 --- a/test/test_load_ref_schema.rb +++ b/test/load_ref_schema_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class LoadRefSchemaTests < Minitest::Test +class LoadRefSchemaTest < Minitest::Test def load_other_schema JSON::Validator.add_schema(JSON::Schema.new( { diff --git a/test/test_merge_missing_values.rb b/test/merge_missing_values_test.rb similarity index 100% rename from test/test_merge_missing_values.rb rename to test/merge_missing_values_test.rb diff --git a/test/test_minitems.rb b/test/min_items_test.rb similarity index 100% rename from test/test_minitems.rb rename to test/min_items_test.rb diff --git a/test/test_one_of.rb b/test/one_of_test.rb similarity index 100% rename from test/test_one_of.rb rename to test/one_of_test.rb diff --git a/test/test_definition.rb b/test/relative_definition_test.rb similarity index 100% rename from test/test_definition.rb rename to test/relative_definition_test.rb diff --git a/test/test_ruby_schema.rb b/test/ruby_schema_test.rb similarity index 100% rename from test/test_ruby_schema.rb rename to test/ruby_schema_test.rb diff --git a/test/test_schema_loader.rb b/test/schema_reader_test.rb similarity index 98% rename from test/test_schema_loader.rb rename to test/schema_reader_test.rb index 1972c830..8801c9d1 100644 --- a/test/test_schema_loader.rb +++ b/test/schema_reader_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class TestSchemaReader < Minitest::Test +class SchemaReaderTest < Minitest::Test ADDRESS_SCHEMA_URI = 'http://json-schema.org/address' ADDRESS_SCHEMA_PATH = File.expand_path('../schemas/address_microformat.json', __FILE__) diff --git a/test/test_schema_validation.rb b/test/schema_validation_test.rb similarity index 99% rename from test/test_schema_validation.rb rename to test/schema_validation_test.rb index 940715e4..7e3dfc5a 100644 --- a/test/test_schema_validation.rb +++ b/test/schema_validation_test.rb @@ -1,7 +1,7 @@ require File.expand_path('../test_helper', __FILE__) require 'tmpdir' -class JSONSchemaValidation < Minitest::Test +class SchemaValidationTest < Minitest::Test def valid_schema_v3 { "$schema" => "http://json-schema.org/draft-03/schema#", diff --git a/test/test_stringify.rb b/test/stringify_test.rb similarity index 100% rename from test/test_stringify.rb rename to test/stringify_test.rb diff --git a/test/test_schema_type_attribute.rb b/test/type_attribute_test.rb similarity index 92% rename from test/test_schema_type_attribute.rb rename to test/type_attribute_test.rb index 5b446e94..47caaab6 100644 --- a/test/test_schema_type_attribute.rb +++ b/test/type_attribute_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class TestSchemaTypeAttribute < Minitest::Test +class TypeAttributeTest < Minitest::Test def test_type_of_data assert_equal(type_of_data(String.new), 'string') assert_equal(type_of_data(Numeric.new), 'number') diff --git a/test/test_uri_related.rb b/test/uri_parsing_test.rb similarity index 97% rename from test/test_uri_related.rb rename to test/uri_parsing_test.rb index 70069ba5..0def8049 100644 --- a/test/test_uri_related.rb +++ b/test/uri_parsing_test.rb @@ -1,7 +1,7 @@ # coding: utf-8 require File.expand_path('../test_helper', __FILE__) -class UriRelatedTest < Minitest::Test +class UriParsingTest < Minitest::Test def test_asian_characters schema = { "$schema"=> "http://json-schema.org/draft-04/schema#", diff --git a/test/test_validator.rb b/test/validator_schema_reader_test.rb similarity index 96% rename from test/test_validator.rb rename to test/validator_schema_reader_test.rb index eb65de61..a15850f4 100644 --- a/test/test_validator.rb +++ b/test/validator_schema_reader_test.rb @@ -1,6 +1,6 @@ require File.expand_path('../test_helper', __FILE__) -class TestValidator < Minitest::Test +class ValidatorSchemaReaderTest < Minitest::Test class MockReader def read(location) From fdf3815b4b2965f854677719e033f9ac5514729e Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Fri, 8 Jan 2016 12:14:51 +0000 Subject: [PATCH 39/43] Moved test_helper.rb into the support directory --- Rakefile | 4 +--- test/all_of_ref_schema_test.rb | 2 +- test/any_of_ref_schema_test.rb | 2 +- test/bad_schema_ref_test.rb | 2 +- test/common_test_suite_test.rb | 2 +- test/custom_format_test.rb | 2 +- test/draft1_test.rb | 2 +- test/draft2_test.rb | 2 +- test/draft3_test.rb | 2 +- test/draft4_test.rb | 2 +- test/extended_schema_test.rb | 2 +- test/extends_nested_test.rb | 2 +- test/files_test.rb | 2 +- test/fragment_resolution_test.rb | 2 +- test/fragment_validation_with_ref_test.rb | 2 +- test/full_validation_test.rb | 2 +- test/initialize_data_test.rb | 2 +- test/list_option_test.rb | 2 +- test/load_ref_schema_test.rb | 2 +- test/merge_missing_values_test.rb | 2 +- test/min_items_test.rb | 2 +- test/one_of_test.rb | 2 +- test/relative_definition_test.rb | 2 +- test/ruby_schema_test.rb | 2 +- test/schema_reader_test.rb | 2 +- test/schema_validation_test.rb | 2 +- test/stringify_test.rb | 2 +- test/{ => support}/test_helper.rb | 10 +++++----- test/type_attribute_test.rb | 2 +- test/uri_parsing_test.rb | 2 +- test/validator_schema_reader_test.rb | 2 +- 31 files changed, 35 insertions(+), 37 deletions(-) rename test/{ => support}/test_helper.rb (73%) diff --git a/Rakefile b/Rakefile index 1e28f7f3..1033ed9f 100644 --- a/Rakefile +++ b/Rakefile @@ -16,9 +16,7 @@ Rake::TestTask.new do |t| t.libs << "." t.warning = true t.verbose = true - t.test_files = FileList.new('test/*_test.rb') do |fl| - fl.exclude(/test_helper\.rb$/) - end + t.test_files = FileList.new('test/*_test.rb') end task :test => :update_common_tests diff --git a/test/all_of_ref_schema_test.rb b/test/all_of_ref_schema_test.rb index 8ab6bf0d..c178333b 100644 --- a/test/all_of_ref_schema_test.rb +++ b/test/all_of_ref_schema_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class AllOfRefSchemaTest < Minitest::Test def schema diff --git a/test/any_of_ref_schema_test.rb b/test/any_of_ref_schema_test.rb index 475222de..5e5ae734 100644 --- a/test/any_of_ref_schema_test.rb +++ b/test/any_of_ref_schema_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class AnyOfRefSchemaTest < Minitest::Test def schema diff --git a/test/bad_schema_ref_test.rb b/test/bad_schema_ref_test.rb index ef4d9761..0ab67f63 100644 --- a/test/bad_schema_ref_test.rb +++ b/test/bad_schema_ref_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) require 'socket' diff --git a/test/common_test_suite_test.rb b/test/common_test_suite_test.rb index 3c9d3aff..1597b91d 100644 --- a/test/common_test_suite_test.rb +++ b/test/common_test_suite_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) require 'json' class CommonTestSuiteTest < Minitest::Test diff --git a/test/custom_format_test.rb b/test/custom_format_test.rb index 4d07e427..084d4914 100644 --- a/test/custom_format_test.rb +++ b/test/custom_format_test.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class CustomFormatTest < Minitest::Test def setup diff --git a/test/draft1_test.rb b/test/draft1_test.rb index 1779392d..b1b3f9d1 100644 --- a/test/draft1_test.rb +++ b/test/draft1_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class Draft1Test < Minitest::Test def schema_version diff --git a/test/draft2_test.rb b/test/draft2_test.rb index 65010411..5a2398a3 100644 --- a/test/draft2_test.rb +++ b/test/draft2_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class Draft2Test < Minitest::Test def schema_version diff --git a/test/draft3_test.rb b/test/draft3_test.rb index e46fab3b..69063110 100644 --- a/test/draft3_test.rb +++ b/test/draft3_test.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class Draft3Test < Minitest::Test def schema_version diff --git a/test/draft4_test.rb b/test/draft4_test.rb index 14378f79..e9474cd4 100644 --- a/test/draft4_test.rb +++ b/test/draft4_test.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class Draft4Test < Minitest::Test def schema_version diff --git a/test/extended_schema_test.rb b/test/extended_schema_test.rb index fe8ea74d..b6b8a76e 100644 --- a/test/extended_schema_test.rb +++ b/test/extended_schema_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class BitwiseAndAttribute < JSON::Schema::Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) diff --git a/test/extends_nested_test.rb b/test/extends_nested_test.rb index 9f6b40db..2e409e04 100644 --- a/test/extends_nested_test.rb +++ b/test/extends_nested_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class ExtendsNestedTest < Minitest::Test diff --git a/test/files_test.rb b/test/files_test.rb index 2d3aa7da..193a19de 100644 --- a/test/files_test.rb +++ b/test/files_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class FilesTest < Minitest::Test diff --git a/test/fragment_resolution_test.rb b/test/fragment_resolution_test.rb index 819e97b8..36e9aee2 100644 --- a/test/fragment_resolution_test.rb +++ b/test/fragment_resolution_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class FragmentResolutionTest < Minitest::Test def test_fragment_resolution diff --git a/test/fragment_validation_with_ref_test.rb b/test/fragment_validation_with_ref_test.rb index 9a92d58d..dbcbd882 100644 --- a/test/fragment_validation_with_ref_test.rb +++ b/test/fragment_validation_with_ref_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class FragmentValidationWithRefTest < Minitest::Test def whole_schema diff --git a/test/full_validation_test.rb b/test/full_validation_test.rb index aa671a0c..0ad8ff6b 100644 --- a/test/full_validation_test.rb +++ b/test/full_validation_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class FullValidationTest < Minitest::Test diff --git a/test/initialize_data_test.rb b/test/initialize_data_test.rb index 77d6c112..1e1e1f27 100644 --- a/test/initialize_data_test.rb +++ b/test/initialize_data_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class InitializeDataTest < Minitest::Test diff --git a/test/list_option_test.rb b/test/list_option_test.rb index 2360cf53..afe3377b 100644 --- a/test/list_option_test.rb +++ b/test/list_option_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class ListOptionTest < Minitest::Test def test_list_option_reusing_schemas diff --git a/test/load_ref_schema_test.rb b/test/load_ref_schema_test.rb index 2f350732..2a3d1927 100644 --- a/test/load_ref_schema_test.rb +++ b/test/load_ref_schema_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class LoadRefSchemaTest < Minitest::Test def load_other_schema diff --git a/test/merge_missing_values_test.rb b/test/merge_missing_values_test.rb index a375a89e..c5c8a216 100644 --- a/test/merge_missing_values_test.rb +++ b/test/merge_missing_values_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class MergeMissingValuesTest < Minitest::Test def test_merge_missing_values_for_string diff --git a/test/min_items_test.rb b/test/min_items_test.rb index d17d2242..0824ea43 100644 --- a/test/min_items_test.rb +++ b/test/min_items_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class MinItemsTest < Minitest::Test def test_minitems_nils diff --git a/test/one_of_test.rb b/test/one_of_test.rb index f26e924f..e4464941 100644 --- a/test/one_of_test.rb +++ b/test/one_of_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class OneOfTest < Minitest::Test def test_one_of_links_schema diff --git a/test/relative_definition_test.rb b/test/relative_definition_test.rb index cc020074..6d13e8c2 100644 --- a/test/relative_definition_test.rb +++ b/test/relative_definition_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class RelativeDefinitionTest < Minitest::Test diff --git a/test/ruby_schema_test.rb b/test/ruby_schema_test.rb index a6e884bd..fba786cb 100644 --- a/test/ruby_schema_test.rb +++ b/test/ruby_schema_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class RubySchemaTest < Minitest::Test def test_string_keys diff --git a/test/schema_reader_test.rb b/test/schema_reader_test.rb index 8801c9d1..5ae07c57 100644 --- a/test/schema_reader_test.rb +++ b/test/schema_reader_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class SchemaReaderTest < Minitest::Test ADDRESS_SCHEMA_URI = 'http://json-schema.org/address' diff --git a/test/schema_validation_test.rb b/test/schema_validation_test.rb index 7e3dfc5a..160ec71c 100644 --- a/test/schema_validation_test.rb +++ b/test/schema_validation_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) require 'tmpdir' class SchemaValidationTest < Minitest::Test diff --git a/test/stringify_test.rb b/test/stringify_test.rb index 99994373..09bbd579 100644 --- a/test/stringify_test.rb +++ b/test/stringify_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class StringifyTest < Minitest::Test def test_stringify_on_hash diff --git a/test/test_helper.rb b/test/support/test_helper.rb similarity index 73% rename from test/test_helper.rb rename to test/support/test_helper.rb index 14510863..6bf315fb 100644 --- a/test/test_helper.rb +++ b/test/support/test_helper.rb @@ -1,20 +1,20 @@ require 'minitest/autorun' require 'webmock/minitest' -$:.unshift(File.expand_path('../../lib', __FILE__)) +$LOAD_PATH.unshift(File.expand_path('../../../lib', __FILE__)) require 'json-schema' -Dir[File.join(File.expand_path('../support', __FILE__), '*.rb')].each do |support_file| - require support_file +Dir[File.join(File.expand_path('../', __FILE__), '*.rb')].each do |support_file| + require support_file unless support_file == __FILE__ end class Minitest::Test def schema_fixture_path(filename) - File.join(File.dirname(__FILE__), 'schemas', filename) + File.join(File.dirname(__FILE__), '../schemas', filename) end def data_fixture_path(filename) - File.join(File.dirname(__FILE__), 'data', filename) + File.join(File.dirname(__FILE__), '../data', filename) end def assert_valid(schema, data, options = {}) diff --git a/test/type_attribute_test.rb b/test/type_attribute_test.rb index 47caaab6..81da466f 100644 --- a/test/type_attribute_test.rb +++ b/test/type_attribute_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class TypeAttributeTest < Minitest::Test def test_type_of_data diff --git a/test/uri_parsing_test.rb b/test/uri_parsing_test.rb index 0def8049..cecd8f97 100644 --- a/test/uri_parsing_test.rb +++ b/test/uri_parsing_test.rb @@ -1,5 +1,5 @@ # coding: utf-8 -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class UriParsingTest < Minitest::Test def test_asian_characters diff --git a/test/validator_schema_reader_test.rb b/test/validator_schema_reader_test.rb index a15850f4..d1e4f67b 100644 --- a/test/validator_schema_reader_test.rb +++ b/test/validator_schema_reader_test.rb @@ -1,4 +1,4 @@ -require File.expand_path('../test_helper', __FILE__) +require File.expand_path('../support/test_helper', __FILE__) class ValidatorSchemaReaderTest < Minitest::Test From 03332fcf86bccb707dc7b67f17ab7b2c1cad9e0e Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 22 Jun 2016 14:54:59 +0100 Subject: [PATCH 40/43] Moved test-specific classes out of the global namespace To avoid unintended side-effects --- test/extended_schema_test.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/extended_schema_test.rb b/test/extended_schema_test.rb index b6b8a76e..5d9ed88b 100644 --- a/test/extended_schema_test.rb +++ b/test/extended_schema_test.rb @@ -1,28 +1,28 @@ require File.expand_path('../support/test_helper', __FILE__) -class BitwiseAndAttribute < JSON::Schema::Attribute - def self.validate(current_schema, data, fragments, processor, validator, options = {}) - return unless data.is_a?(Integer) - - if data & current_schema.schema['bitwise-and'].to_i == 0 - message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-and']}" - validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) +class ExtendedSchemaTest < Minitest::Test + class BitwiseAndAttribute < JSON::Schema::Attribute + def self.validate(current_schema, data, fragments, processor, validator, options = {}) + return unless data.is_a?(Integer) + + if data & current_schema.schema['bitwise-and'].to_i == 0 + message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-and']}" + validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) + end end end -end -class ExtendedSchema < JSON::Schema::Validator - def initialize - super - extend_schema_definition("http://json-schema.org/draft-03/schema#") - @attributes["bitwise-and"] = BitwiseAndAttribute - @uri = Addressable::URI.parse("http://test.com/test.json") - end + class ExtendedSchema < JSON::Schema::Validator + def initialize + super + extend_schema_definition("http://json-schema.org/draft-03/schema#") + @attributes["bitwise-and"] = BitwiseAndAttribute + @uri = Addressable::URI.parse("http://test.com/test.json") + end - JSON::Validator.register_validator(self.new) -end + JSON::Validator.register_validator(self.new) + end -class ExtendedSchemaTest < Minitest::Test def test_extended_schema_validation schema = { "$schema" => "http://test.com/test.json", From eb58a3c95635fbc952399df34474ee33440bafad Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 29 Jun 2016 15:27:09 +0100 Subject: [PATCH 41/43] Made sure we use the latest ruby 2.3 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e027c911..ea6ae31e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ rvm: - "2.0" - "2.1" - "2.2" - - "2.3.0" + - "2.3" - "jruby" - "rbx" From 2fc35df2e90f3bab748b85982708774d7034eb4f Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Wed, 29 Jun 2016 15:45:25 +0100 Subject: [PATCH 42/43] Explictly set ruby 2.3.1 on travis Travis doesn't support 2.3 yet --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ea6ae31e..832bfd18 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ rvm: - "2.0" - "2.1" - "2.2" - - "2.3" + - "2.3.1" - "jruby" - "rbx" @@ -17,11 +17,11 @@ install: matrix: include: - - rvm: "2.3.0" + - rvm: "2.3.1" gemfile: "gemfiles/Gemfile.multi_json.x" - - rvm: "2.3.0" + - rvm: "2.3.1" gemfile: "gemfiles/Gemfile.yajl-ruby.x" - - rvm: "2.3.0" + - rvm: "2.3.1" gemfile: "gemfiles/Gemfile.uuidtools.x" allow_failures: - rvm: "1.8" From 8e5e6dd79c84bf4ef9068cc8d2d30cd16a6a2abe Mon Sep 17 00:00:00 2001 From: Jonas Peschla Date: Thu, 14 Jul 2016 00:50:30 +0200 Subject: [PATCH 43/43] Reapply some changes from alternate backend removal PR and fix tests after merge mistakes --- .travis.yml | 4 -- Gemfile | 5 -- README.md | 19 ------- lib/json-schema/validator.rb | 57 ++------------------ test/initialize_data_test.rb | 6 +-- test/schema_reader_test.rb | 2 +- test/schemas/relative_definition_schema.json | 2 +- test/test-suite | 2 +- 8 files changed, 11 insertions(+), 86 deletions(-) diff --git a/.travis.yml b/.travis.yml index c67273d2..41eb1e6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,9 +16,5 @@ install: matrix: include: - - rvm: "2.3.1" - gemfile: "gemfiles/Gemfile.multi_json.x" - - rvm: "2.3.1" - gemfile: "gemfiles/Gemfile.yajl-ruby.x" - rvm: "2.3.1" gemfile: "gemfiles/Gemfile.uuidtools.x" diff --git a/Gemfile b/Gemfile index dc60a594..06c12768 100644 --- a/Gemfile +++ b/Gemfile @@ -3,8 +3,3 @@ source "https://rubygems.org" gemspec gem "json", ">= 1.7", :platforms => [:mri_19] - -group :development do - gem "rake" - gem "minitest", '~> 5.0' -end diff --git a/README.md b/README.md index b32fafa6..fd66fee9 100644 --- a/README.md +++ b/README.md @@ -389,25 +389,6 @@ The `JSON::Schema::Reader` interface requires only an object which responds to documentation](http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader) for more information. -JSON Backends -------------- - -The JSON Schema library currently supports the `json` and `yajl-ruby` backend -JSON parsers. If either of these libraries are installed, they will be -automatically loaded and used to parse any JSON strings supplied by the user. - -If more than one of the supported JSON backends are installed, the `yajl-ruby` -parser is used by default. This can be changed by issuing the following before -validation: - -```ruby -JSON::Validator.json_backend = :json -``` - -Optionally, the JSON Schema library supports using the MultiJSON library for -selecting JSON backends. If the MultiJSON library is installed, it will be -autoloaded. - Notes ----- diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 0b230514..9fc23447 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -386,55 +386,8 @@ def restore_default_formats(versions = ["draft1", "draft2", "draft3", "draft4", end end - def json_backend - if defined?(MultiJson) - MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine - else - @@json_backend - end - end - - def json_backend=(backend) - if defined?(MultiJson) - backend = backend == 'json' ? 'json_gem' : backend - MultiJson.respond_to?(:use) ? MultiJson.use(backend) : MultiJson.engine = backend - else - 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 - end - - def parse(s) - if defined?(MultiJson) - begin - MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s) - rescue MultiJson::ParseError => e - raise JSON::Schema::JsonParseError.new(e.message) - end - else - case @@json_backend.to_s - when 'json' - begin - JSON.parse(s, :quirks_mode => true) - rescue JSON::ParserError => e - raise JSON::Schema::JsonParseError.new(e.message) - end - when 'yajl' - begin - json = StringIO.new(s) - parser = Yajl::Parser.new - parser.parse(json) or raise JSON::Schema::JsonParseError.new("The JSON could not be parsed by yajl") - rescue Yajl::ParseError => e - raise JSON::Schema::JsonParseError.new(e.message) - end - else - raise JSON::Schema::JsonParseError.new("No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json") - end - end + def parse(string) + JSON.parse(string, quirks_mode: true) end def merge_missing_values(source, destination) @@ -501,7 +454,7 @@ def initialize_schema(schema) schema = schema.to_array_schema end Validator.add_schema(schema) - rescue JSON::Schema::JsonParseError + rescue JSON::ParserError # Build a uri for it schema_uri = Util::URI.normalized_uri(schema) if !self.class.schema_loaded?(schema_uri) @@ -548,11 +501,11 @@ def initialize_data(data) elsif data.is_a?(String) begin data = JSON::Validator.parse(data) - rescue JSON::Schema::JsonParseError + rescue begin json_uri = Util::URI.normalized_uri(data) data = JSON::Validator.parse(custom_open(json_uri)) - rescue JSON::Schema::JsonLoadError + rescue # Silently discard the error - use the data as-is end end diff --git a/test/initialize_data_test.rb b/test/initialize_data_test.rb index 1e1e1f27..5529cc04 100644 --- a/test/initialize_data_test.rb +++ b/test/initialize_data_test.rb @@ -10,7 +10,7 @@ def test_parse_character_string assert(JSON::Validator.validate(schema, data, :parse_data => false)) - assert_raises(JSON::Schema::JsonParseError) do + assert_raises(JSON::ParserError) do JSON::Validator.validate(schema, data, :json => true) end @@ -66,7 +66,7 @@ def test_parse_valid_uri_string assert(JSON::Validator.validate(schema, data, :parse_data => false)) - assert_raises(JSON::Schema::JsonParseError) do + assert_raises(JSON::ParserError) do JSON::Validator.validate(schema, data, :json => true) end @@ -89,7 +89,7 @@ def test_parse_invalid_uri_string assert(JSON::Validator.validate(schema, data, :parse_data => false)) - assert_raises(JSON::Schema::JsonParseError) do + assert_raises(JSON::ParserError) do JSON::Validator.validate(schema, data, :json => true) end diff --git a/test/schema_reader_test.rb b/test/schema_reader_test.rb index 5ae07c57..005f7b1e 100644 --- a/test/schema_reader_test.rb +++ b/test/schema_reader_test.rb @@ -67,7 +67,7 @@ def test_parse_error reader = JSON::Schema::Reader.new - assert_raises(JSON::Schema::JsonParseError) do + assert_raises(JSON::ParserError) do reader.read(ADDRESS_SCHEMA_URI) end end diff --git a/test/schemas/relative_definition_schema.json b/test/schemas/relative_definition_schema.json index 240b35c8..441d66d6 100644 --- a/test/schemas/relative_definition_schema.json +++ b/test/schemas/relative_definition_schema.json @@ -5,4 +5,4 @@ "$ref": "definition_schema.json#/definitions/foo" } } -} \ No newline at end of file +} diff --git a/test/test-suite b/test/test-suite index 2f0d6e36..9355965c 160000 --- a/test/test-suite +++ b/test/test-suite @@ -1 +1 @@ -Subproject commit 2f0d6e3686b0989665b05c4a0b147ea6ce357198 +Subproject commit 9355965c517b91ec586aaaf301cc619d0e3001d2