pax_global_header00006660000000000000000000000064134116756450014526gustar00rootroot0000000000000052 comment=64da0006ebf98cfa2dacab92b895946b3450b72c ruby-json-schema-2.8.1/000077500000000000000000000000001341167564500147245ustar00rootroot00000000000000ruby-json-schema-2.8.1/.gitignore000066400000000000000000000001011341167564500167040ustar00rootroot00000000000000/.project .*.swp pkg *.gem /Gemfile.lock .bundle .idea /coverage ruby-json-schema-2.8.1/.gitmodules000066400000000000000000000002121341167564500170740ustar00rootroot00000000000000[submodule "test/test-suite"] path = test/test-suite branch = master url = git://github.com/json-schema-org/JSON-Schema-Test-Suite.git ruby-json-schema-2.8.1/.travis.yml000066400000000000000000000010031341167564500170270ustar00rootroot00000000000000language: "ruby" rvm: - "1.9" - "2.0" - "2.1" - "2.2" - "2.3" - "2.4" - "2.5" - "jruby-1.7" - "jruby-9.1" sudo: false install: - bundle install --retry=3 matrix: include: - rvm: "1.9" gemfile: "gemfiles/Gemfile.ruby_19.x" - rvm: "jruby-1.7" gemfile: "gemfiles/Gemfile.ruby_19.x" - rvm: "2.5" gemfile: "gemfiles/Gemfile.multi_json.x" - rvm: "2.5" gemfile: "gemfiles/Gemfile.yajl-ruby.x" - rvm: "2.5" gemfile: "gemfiles/Gemfile.uuidtools.x" ruby-json-schema-2.8.1/CHANGELOG.md000066400000000000000000000047721341167564500165470ustar00rootroot00000000000000# 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] ## [2.8.1] - 2019-10-14 ### Changed - All limit classes are now stored in their own files in 'json-schema/attributes/limits' - All attribute classes are now stored in their own files in 'json-schema/attributes' ### Fixed - Corrected the draft6 schema id to `http://json-schema.org/draft/schema#` - Rescue URI error when initializing a data string that contains a colon - Fragments with an odd number of components no longer raise an `undefined method `validate'` error ## [2.8.0] - 2017-02-07 ### Added - Ruby 2.4 support ### Changed - Made the `:clear_cache` option for `validate` also clear the URI parse cache - Moved `JSON::Validator.absolutize_ref` and the ref manipulating code in `JSON::Schema::RefAttribute` into `JSON::Util::URI` - Made validation errors refer to json schema types not ruby types ### Deprecated - `JSON::Validator#validator_for` in favor of `JSON::Validator#validator_for_uri` - `JSON::Validator.validate2` in favor of `JSON::Validator.validate!` - `JSON::Schema::Validator#extend_schema_definition` in favour of subclassing ## [2.7.0] - 2016-09-29 ### Fixed - Made sure we really do clear the cache when instructed to - It's now possible to use reserved words in property names - Removed support for setting "extends" to a string (it's invalid json-schema - use a "$ref" instead) - Relaxed 'items' and 'allowedItems' validation to permit arrays to pass even when they contain fewer elements than the 'items' array. To require full tuples, use 'minItems'. ### Changed - Made all `validate*` methods on `JSON::Validator` ultimately call `validate!` - Updated addressable dependency to 2.4.0 - Attached failed `uri` or `pathname` to read errors for more meaning ## [2.6.2] - 2016-05-13 ### Fixed - Made it possible to include colons in a $ref ### Changed - Reformatted examples in the readme ## [2.6.1] - 2016-02-26 ### 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 - 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` ruby-json-schema-2.8.1/CONTRIBUTING.md000066400000000000000000000015761341167564500171660ustar00rootroot00000000000000The Ruby JSON Schema library is meant to be a community effort, and as such, there are no strict guidelines for contributing. 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, 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. ruby-json-schema-2.8.1/CONTRIBUTORS.md000066400000000000000000000015521341167564500172060ustar00rootroot00000000000000CONTRIBUTORS ------------ * Kenny Hoxworth - @hoxworth * Jenny Duckett - @jennyd * Kevin Glowacz - @kjg * Seb Bacon - @sebbacon * Jonathan Chrisp - @jonathanchrisp * James McKinney - @jpmckinney * Kylo Ginsberg - @kylog * Alex Soto - @apsoto * Roger Leite - @rogerleite * Myron Marston - @myronmarston * Jesse Stuart - @jvatic * Brian Hoffman - @lcdhoffman * Simon Waddington - @goodsimon * Chris Baynes - @chris-baynes * David Barri - @japgolly * Tyler Hunt - @tylerhunt * @vapir * Tom May - @tommay * Chris Johnson - @kindkid * David Kellum - @dekellum * Miguel Herranz - @IPGlider * Nick Recobra - @oruen * Vasily Fedoseyev - @Vasfed * Jari Bakken - @jarib * Kyle Hargraves - @pd * Jamie Cobbett - @jamiecobbett * Iain Beeston - @iainbeeston * Matt Palmer - @mpalmer * Ben Kirzhner - @benkirzhner * RST-J - @RST-J * Christian Treppo - @treppo * Benjamin Falk - @benfalk ruby-json-schema-2.8.1/Gemfile000066400000000000000000000001671341167564500162230ustar00rootroot00000000000000source "https://rubygems.org" gemspec gem "json", ">= 1.7", :platforms => :mri_19 gem 'simplecov', :require => false ruby-json-schema-2.8.1/LICENSE.md000066400000000000000000000020651341167564500163330ustar00rootroot00000000000000Copyright (c) 2010-2011, Lookingglass Cyber Solutions Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.ruby-json-schema-2.8.1/README.md000066400000000000000000000341761341167564500162160ustar00rootroot00000000000000[![Gem Version](https://badge.fury.io/rb/json-schema.svg)](https://badge.fury.io/rb/json-schema) [![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 ========================== 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. Additional Resources -------------------- - [Google Groups](https://groups.google.com/forum/#!forum/ruby-json-schema) - #ruby-json-schema on chat.freenode.net 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. 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 ``` Validation ----- 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 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. For further information on json schema itself refer to Understanding JSON Schema. Basic Usage -------------- ```ruby require "json-schema" schema = { "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "integer"} } } # # validate ruby objects against a ruby schema # # => true JSON::Validator.validate(schema, { "a" => 5 }) # => false JSON::Validator.validate(schema, {}) # # validate a json string against a json schema file # require "json" File.write("schema.json", JSON.dump(schema)) # => true JSON::Validator.validate('schema.json', '{ "a": 5 }') # # raise an error when validation fails # # => "The property '#/a' of type String did not match the following type: integer" begin JSON::Validator.validate!(schema, { "a" => "taco" }) rescue JSON::Schema::ValidationError => e e.message end # # return an array of error messages when validation fails # # => ["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" }) ``` Advanced Options ----------------- ```ruby require "json-schema" schema = { "type"=>"object", "required" => ["a"], "properties" => { "a" => { "type" => "integer", "default" => 42 }, "b" => { "type" => "object", "properties" => { "x" => { "type" => "integer" } } } } } # # 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" } } } # => false JSON::Validator.validate(v2_schema, {}, :version => :draft2) # => true JSON::Validator.validate(v2_schema, {}) # # 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) # # => true JSON::Validator.validate(schema, { "a" => 1 }, :parse_data => false) # => false JSON::Validator.validate(schema, '{ "a": 1 }', :parse_data => false) # # with the `:json` option, the json must be an unparsed json text (not a hash, a uri or a file path) # # => 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 # # with the `:uri` option, the json must be a uri or file path (not a hash or a json text) # File.write("data.json", '{ "a": 1 }') # => 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 # # with the `:clear_cache` option set to true, the internal cache of schemas is # cleared after validation (otherwise schemas are cached for efficiency) # File.write("schema.json", v2_schema.to_json) # => true JSON::Validator.validate("schema.json", {}) File.write("schema.json", schema.to_json) # => true JSON::Validator.validate("schema.json", {}, :clear_cache => true) # => false JSON::Validator.validate("schema.json", {}) ``` 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. ```ruby require "json-schema" class BitwiseAndAttribute < JSON::Schema::Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) if data.is_a?(Integer) && 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-or']}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end class ExtendedSchema < JSON::Schema::Draft3 def initialize super @attributes["bitwise-and"] = BitwiseAndAttribute @uri = JSON::Util::URI.parse("http://test.com/test.json") @names = ["http://test.com/test.json"] end JSON::Validator.register_validator(self.new) end schema = { "$schema" => "http://test.com/test.json", "properties" => { "a" => { "bitwise-and" => 1 }, "b" => { "type" => "string" } } } data = { "a" => 0 } data = {"a" => 1, "b" => "taco"} JSON::Validator.validate(schema,data) # => true data = {"a" => 1, "b" => 5} JSON::Validator.validate(schema,data) # => false data = {"a" => 0, "b" => "taco"} JSON::Validator.validate(schema,data) # => false ``` 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']() ```ruby require "json-schema" format_proc = -> value { raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" } # register the proc for format 'the-answer' for draft4 schema JSON::Validator.register_format_validator("the-answer", format_proc, ["draft4"]) # omitting the version parameter uses ["draft1", "draft2", "draft3", "draft4"] as default JSON::Validator.register_format_validator("the-answer", format_proc) # deregistering the custom validator # (also ["draft1", "draft2", "draft3", "draft4"] as default version) JSON::Validator.deregister_format_validator('the-answer', ["draft4"]) # shortcut to restore the default formats for validators (same default as before) JSON::Validator.restore_default_formats(["draft4"]) # with the validator registered as above, the following results in # ["The property '#a' must be 42"] as returned errors schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => { "type" => "string", "format" => "the-answer", } } } errors = JSON::Validator.fully_validate(schema, {"a" => "23"}) ``` Validating a JSON Schema ------------------------ To validate that a JSON Schema conforms to the JSON Schema standard, you need to validate your schema against the metaschema for the appropriate JSON Schema Draft. All of the normal validation methods can be used for this. First retrieve the appropriate metaschema from the internal cache (using `JSON::Validator.validator_for_name()` or `JSON::Validator.validator_for_uri()`) and then simply validate your schema against it. ```ruby require "json-schema" schema = { "type" => "object", "properties" => { "a" => {"type" => "integer"} } } metaschema = JSON::Validator.validator_for_name("draft4").metaschema # => true JSON::Validator.validate(metaschema, schema) ``` 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: ```ruby 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: ```ruby # Change the default schema reader used JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false) # For this validation call, use a reader which only accepts URIs from my-website.com 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. 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 ----- 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'). Additionally, JSON::Validator does not handle any json hyperschema attributes. ruby-json-schema-2.8.1/Rakefile000066400000000000000000000030641341167564500163740ustar00rootroot00000000000000require 'bundler' require 'rake' require 'rake/testtask' Bundler::GemHelper.install_tasks desc "Updates the json-schema common test suite to the latest version" task :update_common_tests do unless File.read(".git/config").include?('submodule "test/test-suite"') sh "git submodule init" end puts "Updating json-schema common test suite..." begin sh "git submodule update --remote --quiet" rescue StandardError STDERR.puts "Failed to update common test suite." end end desc "Update meta-schemas to the latest version" task :update_meta_schemas do puts "Updating meta-schemas..." id_mappings = { 'http://json-schema.org/draft/schema#' => 'https://raw.githubusercontent.com/json-schema-org/json-schema-spec/master/schema.json' } require 'open-uri' require 'thwait' download_threads = Dir['resources/*.json'].map do |path| schema_id = File.read(path)[/"\$?id"\s*:\s*"(.*?)"/, 1] schema_uri = id_mappings[schema_id] || schema_id Thread.new(schema_uri) do |uri| Thread.current[:uri] = uri begin metaschema = URI(uri).read File.write(path, metaschema) rescue StandardError false end end end ThreadsWait.all_waits(*download_threads) do |t| if t.value puts t[:uri] else STDERR.puts "Failed to update meta-schema #{t[:uri]}" end end end Rake::TestTask.new do |t| t.libs << "." t.warning = true t.verbose = true t.test_files = FileList.new('test/*_test.rb') end task update: [:update_common_tests, :update_meta_schemas] task :default => :test ruby-json-schema-2.8.1/VERSION.yml000066400000000000000000000000331341167564500165700ustar00rootroot00000000000000major: 2 minor: 8 patch: 1 ruby-json-schema-2.8.1/gemfiles/000077500000000000000000000000001341167564500165175ustar00rootroot00000000000000ruby-json-schema-2.8.1/gemfiles/Gemfile.multi_json.x000066400000000000000000000001101341167564500224320ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "multi_json" ruby-json-schema-2.8.1/gemfiles/Gemfile.ruby_19.x000066400000000000000000000001741341167564500215530ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "json", "~> 1.0" gem "addressable", "< 2.5" gem "webmock", "< 3" ruby-json-schema-2.8.1/gemfiles/Gemfile.uuidtools.x000066400000000000000000000001071341167564500223040ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "uuidtools" ruby-json-schema-2.8.1/gemfiles/Gemfile.yajl-ruby.x000066400000000000000000000001071341167564500221730ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "yajl-ruby" ruby-json-schema-2.8.1/json-schema.gemspec000066400000000000000000000015761341167564500205110ustar00rootroot00000000000000require 'yaml' version_yaml = YAML.load(File.open('VERSION.yml').read) version = "#{version_yaml['major']}.#{version_yaml['minor']}.#{version_yaml['patch']}" gem_name = "json-schema" Gem::Specification.new do |s| s.name = gem_name s.version = version s.authors = ["Kenny Hoxworth"] s.email = "hoxworth@gmail.com" s.homepage = "http://github.com/ruby-json-schema/json-schema/tree/master" s.summary = "Ruby JSON Schema Validator" s.files = Dir[ "lib/**/*", "resources/*.json" ] s.require_path = "lib" s.extra_rdoc_files = ["README.md","LICENSE.md"] s.required_ruby_version = ">= 1.9" s.license = "MIT" s.required_rubygems_version = ">= 1.8" s.add_development_dependency "rake" s.add_development_dependency "minitest", '~> 5.0' s.add_development_dependency "webmock" s.add_development_dependency "bundler" s.add_runtime_dependency "addressable", '>= 2.4' end ruby-json-schema-2.8.1/lib/000077500000000000000000000000001341167564500154725ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema.rb000066400000000000000000000013561341167564500202330ustar00rootroot00000000000000require 'rubygems' if Gem::Specification::find_all_by_name('multi_json').any? require 'multi_json' # Force MultiJson to load an engine before we define the JSON constant here; otherwise, # it looks for things that are under the JSON namespace that aren't there (since we have defined it here) MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine end require 'json-schema/util/array_set' require 'json-schema/util/uri' require 'json-schema/schema' require 'json-schema/schema/reader' require 'json-schema/validator' Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/**/*.rb")].each {|file| require file } Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*.rb")].sort!.each {|file| require file } ruby-json-schema-2.8.1/lib/json-schema/000077500000000000000000000000001341167564500177015ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/attribute.rb000066400000000000000000000027651341167564500222430ustar00rootroot00000000000000require 'json-schema/errors/validation_error' module JSON class Schema class Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) end def self.build_fragment(fragments) "#/#{fragments.join('/')}" end def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors) error = ValidationError.new(message, fragments, failed_attribute, current_schema) if record_errors processor.validation_error(error) else raise error end end def self.validation_errors(validator) validator.validation_errors end TYPE_CLASS_MAPPINGS = { "string" => String, "number" => Numeric, "integer" => Integer, "boolean" => [TrueClass, FalseClass], "object" => Hash, "array" => Array, "null" => NilClass, "any" => Object } def self.data_valid_for_type?(data, type) valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) { return true } Array(valid_classes).any? { |c| data.is_a?(c) } end # Lookup Schema type of given class instance def self.type_of_data(data) type, _ = TYPE_CLASS_MAPPINGS.map { |k,v| [k,v] }.sort_by { |(_, v)| -Array(v).map { |klass| klass.ancestors.size }.max }.find { |(_, v)| Array(v).any? { |klass| data.kind_of?(klass) } } type end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/000077500000000000000000000000001341167564500220675ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/attributes/additionalitems.rb000066400000000000000000000020631341167564500255670ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class AdditionalItemsAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Array) schema = current_schema.schema return unless schema['items'].is_a?(Array) case schema['additionalItems'] when false if schema['items'].length < data.length message = "The property '#{build_fragment(fragments)}' contains additional array elements outside of the schema when none are allowed" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end when Hash additional_items_schema = JSON::Schema.new(schema['additionalItems'], current_schema.uri, validator) data.each_with_index do |item, i| next if i < schema['items'].length additional_items_schema.validate(item, fragments + [i.to_s], processor, options) end end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/additionalproperties.rb000066400000000000000000000044511341167564500266450ustar00rootroot00000000000000require 'json-schema/attribute' require 'json-schema/attributes/extends' module JSON class Schema class AdditionalPropertiesAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) schema = current_schema.schema return unless data.is_a?(Hash) && (schema['type'].nil? || schema['type'] == 'object') extra_properties = remove_valid_properties(data.keys, current_schema, validator) addprop = schema['additionalProperties'] if addprop.is_a?(Hash) matching_properties = extra_properties # & addprop.keys matching_properties.each do |key| additional_property_schema = JSON::Schema.new(addprop, current_schema.uri, validator) additional_property_schema.validate(data[key], fragments + [key], processor, options) end extra_properties -= matching_properties end if extra_properties.any? && (addprop == false || (addprop.is_a?(Hash) && !addprop.empty?)) message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end def self.remove_valid_properties(extra_properties, current_schema, validator) schema = current_schema.schema if schema['properties'] extra_properties = extra_properties - schema['properties'].keys end if schema['patternProperties'] schema['patternProperties'].each_key do |key| regexp = Regexp.new(key) extra_properties.reject! { |prop| regexp.match(prop) } end end if extended_schemas = schema['extends'] extended_schemas = [extended_schemas] unless extended_schemas.is_a?(Array) extended_schemas.each do |schema_value| _, extended_schema = JSON::Schema::ExtendsAttribute.get_extended_uri_and_schema(schema_value, current_schema, validator) if extended_schema extra_properties = remove_valid_properties(extra_properties, extended_schema, validator) end end end extra_properties end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/allof.rb000066400000000000000000000031171341167564500235130ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class AllOfAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) # Create an hash to hold errors that are generated during validation errors = Hash.new { |hsh, k| hsh[k] = [] } valid = true current_schema.schema['allOf'].each_with_index do |element, schema_index| schema = JSON::Schema.new(element,current_schema.uri,validator) # We're going to add a little cruft here to try and maintain any validation errors that occur in the allOf # We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto an error array pre_validation_error_count = validation_errors(processor).count begin schema.validate(data,fragments,processor,options) rescue ValidationError valid = false end diff = validation_errors(processor).count - pre_validation_error_count while diff > 0 diff = diff - 1 errors["allOf ##{schema_index}"].push(validation_errors(processor).pop) end end if !valid || !errors.empty? message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match all of the required schemas" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) validation_errors(processor).last.sub_errors = errors end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/anyof.rb000066400000000000000000000034771341167564500235430ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class AnyOfAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) # Create a hash to hold errors that are generated during validation errors = Hash.new { |hsh, k| hsh[k] = [] } valid = false original_data = data.is_a?(Hash) ? data.clone : data current_schema.schema['anyOf'].each_with_index do |element, schema_index| schema = JSON::Schema.new(element,current_schema.uri,validator) # We're going to add a little cruft here to try and maintain any validation errors that occur in the anyOf # We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto a union error pre_validation_error_count = validation_errors(processor).count begin schema.validate(data,fragments,processor,options) valid = true rescue ValidationError # We don't care that these schemas don't validate - we only care that one validated end diff = validation_errors(processor).count - pre_validation_error_count valid = false if diff > 0 while diff > 0 diff = diff - 1 errors["anyOf ##{schema_index}"].push(validation_errors(processor).pop) end break if valid data = original_data end if !valid message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match one or more of the required schemas" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) validation_errors(processor).last.sub_errors = errors end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/dependencies.rb000066400000000000000000000027701341167564500250500ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class DependenciesAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) current_schema.schema['dependencies'].each do |property, dependency_value| next unless data.has_key?(property.to_s) next unless accept_value?(dependency_value) case dependency_value when String validate_dependency(current_schema, data, property, dependency_value, fragments, processor, self, options) when Array dependency_value.each do |value| validate_dependency(current_schema, data, property, value, fragments, processor, self, options) end else schema = JSON::Schema.new(dependency_value, current_schema.uri, validator) schema.validate(data, fragments, processor, options) end end end def self.validate_dependency(schema, data, property, value, fragments, processor, attribute, options) return if data.key?(value.to_s) message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'" validation_error(processor, message, fragments, schema, attribute, options[:record_errors]) end def self.accept_value?(value) value.is_a?(String) || value.is_a?(Array) || value.is_a?(Hash) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/dependencies_v4.rb000066400000000000000000000003641341167564500254560ustar00rootroot00000000000000require 'json-schema/attributes/dependencies' module JSON class Schema class DependenciesV4Attribute < DependenciesAttribute def self.accept_value?(value) value.is_a?(Array) || value.is_a?(Hash) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/disallow.rb000066400000000000000000000006061341167564500242340ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class DisallowAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless type = validator.attributes['type'] type.validate(current_schema, data, fragments, processor, validator, options.merge(:disallow => true)) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/divisibleby.rb000066400000000000000000000012611341167564500247210ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class DivisibleByAttribute < Attribute def self.keyword 'divisibleBy' end def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Numeric) factor = current_schema.schema[keyword] if factor == 0 || factor == 0.0 || (BigDecimal(data.to_s) % BigDecimal(factor.to_s)).to_f != 0 message = "The property '#{build_fragment(fragments)}' was not divisible by #{factor}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/enum.rb000066400000000000000000000013661341167564500233660ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class EnumAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) enum = current_schema.schema['enum'] return if enum.include?(data) values = enum.map { |val| case val when nil then 'null' when Array then 'array' when Hash then 'object' else val.to_s end }.join(', ') message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match one of the following values: #{values}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/extends.rb000066400000000000000000000032651341167564500240740ustar00rootroot00000000000000require 'json-schema/attribute' require 'json-schema/attributes/ref' module JSON class Schema class ExtendsAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) schemas = current_schema.schema['extends'] schemas = [schemas] if !schemas.is_a?(Array) schemas.each do |s| uri,schema = get_extended_uri_and_schema(s, current_schema, validator) if schema schema.validate(data, fragments, processor, options) elsif uri message = "The extended schema '#{uri.to_s}' cannot be found" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) else message = "The property '#{build_fragment(fragments)}' was not a valid schema" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end def self.get_extended_uri_and_schema(s, current_schema, validator) uri,schema = nil,nil if s.is_a?(Hash) uri = current_schema.uri if s['$ref'] ref_uri,ref_schema = JSON::Schema::RefAttribute.get_referenced_uri_and_schema(s, current_schema, validator) if ref_schema if s.size == 1 # Check if anything else apart from $ref uri,schema = ref_uri,ref_schema else s = s.dup s.delete '$ref' s = ref_schema.schema.merge(s) end end end schema ||= JSON::Schema.new(s,uri,validator) end [uri,schema] end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/format.rb000066400000000000000000000010001341167564500236730ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class FormatAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data_valid_for_type?(data, current_schema.schema['type']) format = current_schema.schema['format'].to_s validator = validator.formats[format] validator.validate(current_schema, data, fragments, processor, validator, options) unless validator.nil? end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/000077500000000000000000000000001341167564500235425ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/custom.rb000066400000000000000000000012571341167564500254060ustar00rootroot00000000000000require 'json-schema/attributes/format' require 'json-schema/errors/custom_format_error' module JSON class Schema class CustomFormat < FormatAttribute def initialize(validation_proc) @validation_proc = validation_proc end def validate(current_schema, data, fragments, processor, validator, options = {}) begin @validation_proc.call data rescue JSON::Schema::CustomFormatError => e message = "The property '#{self.class.build_fragment(fragments)}' #{e.message}" self.class.validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/date.rb000066400000000000000000000015521341167564500250070ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class DateFormat < FormatAttribute REGEXP = /\A\d{4}-\d{2}-\d{2}\z/ def self.validate(current_schema, data, fragments, processor, validator, options = {}) if data.is_a?(String) error_message = "The property '#{build_fragment(fragments)}' must be a date in the format of YYYY-MM-DD" if REGEXP.match(data) begin Date.parse(data) rescue ArgumentError => e raise e unless e.message == 'invalid date' validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end else validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/date_time.rb000066400000000000000000000033061341167564500260240ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class DateTimeFormat < FormatAttribute REGEXP = /\A\d{4}-\d{2}-\d{2}T(\d{2}):(\d{2}):(\d{2})([\.,]\d+)?(Z|[+-](\d{2})(:?\d{2})?)?\z/ def self.validate(current_schema, data, fragments, processor, validator, options = {}) # Timestamp in restricted ISO-8601 YYYY-MM-DDThh:mm:ssZ with optional decimal fraction of the second if data.is_a?(String) error_message = "The property '#{build_fragment(fragments)}' must be a date/time in the ISO-8601 format of YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss.ssZ" if (m = REGEXP.match(data)) parts = data.split("T") begin Date.parse(parts[0]) rescue ArgumentError => e raise e unless e.message == 'invalid date' validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) return 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 end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/date_time_v4.rb000066400000000000000000000010511341167564500264300ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class DateTimeV4Format < FormatAttribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(String) DateTime.rfc3339(data) rescue ArgumentError error_message = "The property '#{build_fragment(fragments)}' must be a valid RFC3339 date/time string" validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/ip.rb000066400000000000000000000020211341167564500244720ustar00rootroot00000000000000require 'json-schema/attributes/format' require 'ipaddr' require 'socket' module JSON class Schema class IPFormat < FormatAttribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(String) begin ip = IPAddr.new(data) rescue ArgumentError => e raise e unless e.message == 'invalid address' end family = ip_version == 6 ? Socket::AF_INET6 : Socket::AF_INET unless ip && ip.family == family error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv#{ip_version} address" validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end def self.ip_version raise NotImplementedError end end class IP4Format < IPFormat def self.ip_version 4 end end class IP6Format < IPFormat def self.ip_version 6 end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/time.rb000066400000000000000000000020131341167564500250210ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class TimeFormat < FormatAttribute REGEXP = /\A(\d{2}):(\d{2}):(\d{2})\z/ def self.validate(current_schema, data, fragments, processor, validator, options = {}) if data.is_a?(String) error_message = "The property '#{build_fragment(fragments)}' must be a time in the format of hh:mm:ss" if (m = REGEXP.match(data)) 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 end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/formats/uri.rb000066400000000000000000000011421341167564500246640ustar00rootroot00000000000000require 'json-schema/attributes/format' require 'json-schema/errors/uri_error' module JSON class Schema class UriFormat < FormatAttribute 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 JSON::Util::URI.parse(data) rescue JSON::Schema::UriError validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/items.rb000066400000000000000000000015201341167564500235330ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class ItemsAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Array) items = current_schema.schema['items'] case items when Hash schema = JSON::Schema.new(items, current_schema.uri, validator) data.each_with_index do |item, i| schema.validate(item, fragments + [i.to_s], processor, options) end when Array items.each_with_index do |item_schema, i| break if i >= data.length schema = JSON::Schema.new(item_schema, current_schema.uri, validator) schema.validate(data[i], fragments + [i.to_s], processor, options) end end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limit.rb000066400000000000000000000024251341167564500235350ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class LimitAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) schema = current_schema.schema return unless data.is_a?(acceptable_type) && invalid?(schema, value(data)) property = build_fragment(fragments) description = error_message(schema) message = format("The property '%s' %s", property, description) validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end def self.invalid?(schema, data) exclusive = exclusive?(schema) limit = limit(schema) if limit_name.start_with?('max') exclusive ? data >= limit : data > limit else exclusive ? data <= limit : data < limit end end def self.limit(schema) schema[limit_name] end def self.exclusive?(schema) false end def self.value(data) data end def self.acceptable_type raise NotImplementedError end def self.error_message(schema) raise NotImplementedError end def self.limit_name raise NotImplementedError end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/000077500000000000000000000000001341167564500233705ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/items.rb000066400000000000000000000003651341167564500250420ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class ItemsLimitAttribute < LimitAttribute def self.acceptable_type Array end def self.value(data) data.length end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/length.rb000066400000000000000000000003671341167564500252040ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class LengthLimitAttribute < LimitAttribute def self.acceptable_type String end def self.value(data) data.length end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/max_items.rb000066400000000000000000000004601341167564500257030ustar00rootroot00000000000000require 'json-schema/attributes/limits/items' module JSON class Schema class MaxItemsAttribute < ItemsLimitAttribute def self.limit_name 'maxItems' end def self.error_message(schema) "had more items than the allowed #{limit(schema)}" end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/max_length.rb000066400000000000000000000004721341167564500260460ustar00rootroot00000000000000require 'json-schema/attributes/limits/length' module JSON class Schema class MaxLengthAttribute < LengthLimitAttribute def self.limit_name 'maxLength' end def self.error_message(schema) "was not of a maximum string length of #{limit(schema)}" end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/max_properties.rb000066400000000000000000000005111341167564500267530ustar00rootroot00000000000000require 'json-schema/attributes/limits/properties' module JSON class Schema class MaxPropertiesAttribute < PropertiesLimitAttribute def self.limit_name 'maxProperties' end def self.error_message(schema) "had more properties than the allowed #{limit(schema)}" end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/maximum.rb000066400000000000000000000004271341167564500253750ustar00rootroot00000000000000require 'json-schema/attributes/limits/numeric' module JSON class Schema class MaximumAttribute < NumericLimitAttribute def self.limit_name 'maximum' end def self.exclusive?(schema) schema['exclusiveMaximum'] end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/maximum_inclusive.rb000066400000000000000000000003541341167564500274550ustar00rootroot00000000000000require 'json-schema/attributes/limits/maximum' module JSON class Schema class MaximumInclusiveAttribute < MaximumAttribute def self.exclusive?(schema) schema['maximumCanEqual'] == false end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/min_items.rb000066400000000000000000000004721341167564500257040ustar00rootroot00000000000000require 'json-schema/attributes/limits/items' module JSON class Schema class MinItemsAttribute < ItemsLimitAttribute def self.limit_name 'minItems' end def self.error_message(schema) "did not contain a minimum number of items #{limit(schema)}" end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/min_length.rb000066400000000000000000000004721341167564500260440ustar00rootroot00000000000000require 'json-schema/attributes/limits/length' module JSON class Schema class MinLengthAttribute < LengthLimitAttribute def self.limit_name 'minLength' end def self.error_message(schema) "was not of a minimum string length of #{limit(schema)}" end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/min_properties.rb000066400000000000000000000005231341167564500267540ustar00rootroot00000000000000require 'json-schema/attributes/limits/properties' module JSON class Schema class MinPropertiesAttribute < PropertiesLimitAttribute def self.limit_name 'minProperties' end def self.error_message(schema) "did not contain a minimum number of properties #{limit(schema)}" end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/minimum.rb000066400000000000000000000004271341167564500253730ustar00rootroot00000000000000require 'json-schema/attributes/limits/numeric' module JSON class Schema class MinimumAttribute < NumericLimitAttribute def self.limit_name 'minimum' end def self.exclusive?(schema) schema['exclusiveMinimum'] end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/minimum_inclusive.rb000066400000000000000000000003541341167564500274530ustar00rootroot00000000000000require 'json-schema/attributes/limits/minimum' module JSON class Schema class MinimumInclusiveAttribute < MinimumAttribute def self.exclusive?(schema) schema['minimumCanEqual'] == false end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/numeric.rb000066400000000000000000000006241341167564500253610ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class NumericLimitAttribute < LimitAttribute def self.acceptable_type Numeric end def self.error_message(schema) exclusivity = exclusive?(schema) ? 'exclusively' : 'inclusively' format("did not have a %s value of %s, %s", limit_name, limit(schema), exclusivity) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/limits/properties.rb000066400000000000000000000003671341167564500261170ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class PropertiesLimitAttribute < LimitAttribute def self.acceptable_type Hash end def self.value(data) data.size end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/maxdecimal.rb000066400000000000000000000012231341167564500245160ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class MaxDecimalAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Numeric) max_decimal_places = current_schema.schema['maxDecimal'] s = data.to_s.split(".")[1] if s && s.length > max_decimal_places message = "The property '#{build_fragment(fragments)}' had more decimal places than the allowed #{max_decimal_places}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/multipleof.rb000066400000000000000000000003061341167564500245730ustar00rootroot00000000000000require 'json-schema/attributes/divisibleby' module JSON class Schema class MultipleOfAttribute < DivisibleByAttribute def self.keyword 'multipleOf' end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/not.rb000066400000000000000000000021551341167564500232170ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class NotAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) schema = JSON::Schema.new(current_schema.schema['not'],current_schema.uri,validator) failed = true errors_copy = processor.validation_errors.clone begin schema.validate(data,fragments,processor,options) # If we're recording errors, we don't throw an exception. Instead, check the errors array length if options[:record_errors] && errors_copy.length != processor.validation_errors.length processor.validation_errors.replace(errors_copy) else message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} matched the disallowed schema" failed = false end rescue ValidationError # Yay, we failed validation. end unless failed validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/oneof.rb000066400000000000000000000036161341167564500235300ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class OneOfAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) errors = Hash.new { |hsh, k| hsh[k] = [] } validation_error_count = 0 one_of = current_schema.schema['oneOf'] original_data = data.is_a?(Hash) ? data.clone : data success_data = nil valid = false one_of.each_with_index do |element, schema_index| schema = JSON::Schema.new(element,current_schema.uri,validator) pre_validation_error_count = validation_errors(processor).count begin schema.validate(data,fragments,processor,options) success_data = data.is_a?(Hash) ? data.clone : data valid = true rescue ValidationError valid = false end diff = validation_errors(processor).count - pre_validation_error_count valid = false if diff > 0 validation_error_count += 1 if !valid while diff > 0 diff = diff - 1 errors["oneOf ##{schema_index}"].push(validation_errors(processor).pop) end data = original_data end if validation_error_count == one_of.length - 1 data = success_data return end if validation_error_count == one_of.length message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match any of the required schemas" else message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} matched more than one of the required schemas" end validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) if message validation_errors(processor).last.sub_errors = errors if message end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/pattern.rb000066400000000000000000000011631341167564500240720ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class PatternAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(String) pattern = current_schema.schema['pattern'] regexp = Regexp.new(pattern) unless regexp.match(data) message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match the regex '#{pattern}'" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/patternproperties.rb000066400000000000000000000013451341167564500262110ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class PatternPropertiesAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) current_schema.schema['patternProperties'].each do |property, property_schema| regexp = Regexp.new(property) # Check each key in the data hash to see if it matches the regex data.each do |key, value| next unless regexp.match(key) schema = JSON::Schema.new(property_schema, current_schema.uri, validator) schema.validate(data[key], fragments + [key], processor, options) end end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/properties.rb000066400000000000000000000045231341167564500246140ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class PropertiesAttribute < Attribute def self.required?(schema, options) schema.fetch('required') { options[:strict] } end def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) schema = current_schema.schema schema['properties'].each do |property, property_schema| property = property.to_s if !data.key?(property) && options[:insert_defaults] && property_schema.has_key?('default') && !property_schema['readonly'] default = property_schema['default'] data[property] = default.is_a?(Hash) ? default.clone : default end if required?(property_schema, options) && !data.has_key?(property) message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end if data.has_key?(property) expected_schema = JSON::Schema.new(property_schema, current_schema.uri, validator) expected_schema.validate(data[property], fragments + [property], processor, options) end end # When strict is true, ensure no undefined properties exist in the data return unless options[:strict] == true && !schema.key?('additionalProperties') diff = data.select do |k, v| k = k.to_s if schema.has_key?('patternProperties') match = false schema['patternProperties'].each do |property, property_schema| regexp = Regexp.new(property) if regexp.match(k) match = true break end end !schema['properties'].has_key?(k) && !match else !schema['properties'].has_key?(k) end end if diff.size > 0 properties = diff.keys.join(', ') message = "The property '#{build_fragment(fragments)}' contained undefined properties: '#{properties}'" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/properties_optional.rb000066400000000000000000000017171341167564500265230ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class PropertiesOptionalAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) schema = current_schema.schema schema['properties'].each do |property, property_schema| property = property.to_s if !property_schema['optional'] && !data.key?(property) message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end if data.has_key?(property) expected_schema = JSON::Schema.new(property_schema, current_schema.uri, validator) expected_schema.validate(data[property], fragments + [property], processor, options) end end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/properties_v4.rb000066400000000000000000000005641341167564500252260ustar00rootroot00000000000000require 'json-schema/attributes/properties' module JSON class Schema class PropertiesV4Attribute < PropertiesAttribute # draft4 relies on its own RequiredAttribute validation at a higher level, rather than # as an attribute of individual properties. def self.required?(schema, options) options[:strict] == true end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/ref.rb000066400000000000000000000044601341167564500231740ustar00rootroot00000000000000require 'json-schema/attribute' require 'json-schema/errors/schema_error' require 'json-schema/util/uri' module JSON class Schema class RefAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) uri,schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator) if schema schema.validate(data, fragments, processor, options) elsif uri message = "The referenced schema '#{uri.to_s}' cannot be found" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) else message = "The property '#{build_fragment(fragments)}' was not a valid schema" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end def self.get_referenced_uri_and_schema(s, current_schema, validator) uri,schema = nil,nil temp_uri = JSON::Util::URI.normalize_ref(s['$ref'], current_schema.uri) # Grab the parent schema from the schema list schema_key = temp_uri.to_s.split("#")[0] + "#" ref_schema = JSON::Validator.schema_for_uri(schema_key) if ref_schema # Perform fragment resolution to retrieve the appropriate level for the schema target_schema = ref_schema.schema fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split("/") fragment_path = '' fragments.each do |fragment| if fragment && fragment != '' fragment = fragment.gsub('~0', '~').gsub('~1', '/') if target_schema.is_a?(Array) target_schema = target_schema[fragment.to_i] else target_schema = target_schema[fragment] end fragment_path = fragment_path + "/#{fragment}" if target_schema.nil? raise SchemaError.new("The fragment '#{fragment_path}' does not exist on schema #{ref_schema.uri.to_s}") end end end # We have the schema finally, build it and validate! uri = temp_uri schema = JSON::Schema.new(target_schema,temp_uri,validator) end [uri,schema] end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/required.rb000066400000000000000000000020301341167564500242270ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class RequiredAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) schema = current_schema.schema defined_properties = schema['properties'] schema['required'].each do |property, property_schema| next if data.has_key?(property.to_s) prop_defaults = options[:insert_defaults] && defined_properties && defined_properties[property] && !defined_properties[property]["default"].nil? && !defined_properties[property]["readonly"] if !prop_defaults message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/type.rb000066400000000000000000000057051341167564500234040ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class TypeAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) union = true if options[:disallow] types = current_schema.schema['disallow'] else types = current_schema.schema['type'] end if !types.is_a?(Array) types = [types] union = false end valid = false # Create a hash to hold errors that are generated during union validation union_errors = Hash.new { |hsh, k| hsh[k] = [] } types.each_with_index do |type, type_index| if type.is_a?(String) valid = data_valid_for_type?(data, type) elsif type.is_a?(Hash) && union # Validate as a schema schema = JSON::Schema.new(type,current_schema.uri,validator) # We're going to add a little cruft here to try and maintain any validation errors that occur in this union type # We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto a union error pre_validation_error_count = validation_errors(processor).count begin schema.validate(data,fragments,processor,options.merge(:disallow => false)) valid = true rescue ValidationError # We don't care that these schemas don't validate - we only care that one validated end diff = validation_errors(processor).count - pre_validation_error_count valid = false if diff > 0 while diff > 0 diff = diff - 1 union_errors["type ##{type_index}"].push(validation_errors(processor).pop) end end break if valid end if options[:disallow] return if !valid message = "The property '#{build_fragment(fragments)}' matched one or more of the following types: #{list_types(types)}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) elsif !valid if union message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match one or more of the following types: #{list_types(types)}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) validation_errors(processor).last.sub_errors = union_errors else message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match the following type: #{list_types(types)}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end def self.list_types(types) types.map { |type| type.is_a?(String) ? type : '(schema)' }.join(', ') end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/type_v4.rb000066400000000000000000000016121341167564500240060ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class TypeV4Attribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) union = true types = current_schema.schema['type'] if !types.is_a?(Array) types = [types] union = false end return if types.any? { |type| data_valid_for_type?(data, type) } types = types.map { |type| type.is_a?(String) ? type : '(schema)' }.join(', ') message = format( "The property '%s' of type %s did not match %s: %s", build_fragment(fragments), type_of_data(data), union ? 'one or more of the following types' : 'the following type', types ) validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end ruby-json-schema-2.8.1/lib/json-schema/attributes/uniqueitems.rb000066400000000000000000000007761341167564500247760ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class UniqueItemsAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Array) if data.clone.uniq! message = "The property '#{build_fragment(fragments)}' contained duplicated array values" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end ruby-json-schema-2.8.1/lib/json-schema/errors/000077500000000000000000000000001341167564500212155ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/errors/custom_format_error.rb000066400000000000000000000001311341167564500256300ustar00rootroot00000000000000module JSON class Schema class CustomFormatError < StandardError end end end ruby-json-schema-2.8.1/lib/json-schema/errors/json_load_error.rb000066400000000000000000000001251341167564500247210ustar00rootroot00000000000000module JSON class Schema class JsonLoadError < StandardError end end end ruby-json-schema-2.8.1/lib/json-schema/errors/json_parse_error.rb000066400000000000000000000001261341167564500251150ustar00rootroot00000000000000module JSON class Schema class JsonParseError < StandardError end end end ruby-json-schema-2.8.1/lib/json-schema/errors/schema_error.rb000066400000000000000000000001231341167564500242070ustar00rootroot00000000000000module JSON class Schema class SchemaError < StandardError end end end ruby-json-schema-2.8.1/lib/json-schema/errors/schema_parse_error.rb000066400000000000000000000001631341167564500254050ustar00rootroot00000000000000require 'json/common' module JSON class Schema class SchemaParseError < JSON::ParserError end end end ruby-json-schema-2.8.1/lib/json-schema/errors/uri_error.rb000066400000000000000000000001201341167564500235430ustar00rootroot00000000000000module JSON class Schema class UriError < StandardError end end end ruby-json-schema-2.8.1/lib/json-schema/errors/validation_error.rb000066400000000000000000000031371341167564500251110ustar00rootroot00000000000000module JSON class Schema class ValidationError < StandardError INDENT = " " attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message def initialize(message, fragments, failed_attribute, schema) @fragments = fragments.clone @schema = schema @sub_errors = {} @failed_attribute = failed_attribute @message = message super(message_with_schema) end def to_string(subschema_level = 0) if @sub_errors.empty? subschema_level == 0 ? message_with_schema : message else messages = ["#{message}. The schema specific errors were:\n"] @sub_errors.each do |subschema, errors| messages.push "- #{subschema}:" messages.concat Array(errors).map { |e| "#{INDENT}- #{e.to_string(subschema_level + 1)}" } end messages.map { |m| (INDENT * subschema_level) + m }.join("\n") end end def to_hash base = {:schema => @schema.uri, :fragment => ::JSON::Schema::Attribute.build_fragment(fragments), :message => message_with_schema, :failed_attribute => @failed_attribute.to_s.split(":").last.split("Attribute").first} if !@sub_errors.empty? base[:errors] = @sub_errors.inject({}) do |hsh, (subschema, errors)| subschema_sym = subschema.downcase.gsub(/\W+/, '_').to_sym hsh[subschema_sym] = Array(errors).map{|e| e.to_hash} hsh end end base end def message_with_schema "#{message} in schema #{schema.uri}" end end end end ruby-json-schema-2.8.1/lib/json-schema/schema.rb000066400000000000000000000033001341167564500214620ustar00rootroot00000000000000require 'pathname' module JSON class Schema attr_accessor :schema, :uri, :validator def initialize(schema,uri,parent_validator=nil) @schema = schema @uri = uri # If there is an ID on this schema, use it to generate the URI if @schema['id'] && @schema['id'].kind_of?(String) temp_uri = JSON::Util::URI.parse(@schema['id']) if temp_uri.relative? temp_uri = uri.join(temp_uri) end @uri = temp_uri end @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'] @validator = JSON::Validator.validator_for_uri(@schema['$schema']) elsif parent_validator @validator = parent_validator else @validator = JSON::Validator.default_validator end end def validate(data, fragments, processor, options = {}) @validator.validate(self, data, fragments, processor, options) end def self.stringify(schema) case schema when Hash then Hash[schema.map { |key, value| [key.to_s, stringify(schema[key])] }] when Array then schema.map do |schema_item| stringify(schema_item) end when Symbol then schema.to_s else schema end end # @return [JSON::Schema] a new schema matching an array whose items all match this schema. def to_array_schema array_schema = { 'type' => 'array', 'items' => schema } array_schema['$schema'] = schema['$schema'] unless schema['$schema'].nil? self.class.new(array_schema, uri, validator) end def to_s @schema.to_json end end end ruby-json-schema-2.8.1/lib/json-schema/schema/000077500000000000000000000000001341167564500211415ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/schema/reader.rb000066400000000000000000000106711341167564500227350ustar00rootroot00000000000000require 'open-uri' require 'pathname' module JSON class Schema # Base for any reading exceptions encountered by {JSON::Schema::Reader} class ReadError < StandardError # @return [String] the requested schema location which was refused attr_reader :location # @return [Symbol] either +:uri+ or +:file+ attr_reader :type def initialize(location, type) @location = location @type = type super(error_message) end private def type_string type == :uri ? 'URI' : type.to_s end end # Raised by {JSON::Schema::Reader} when one of its settings indicate # a schema should not be read. class ReadRefused < ReadError private def error_message "Read of #{type_string} at #{location} refused" end end # Raised by {JSON::Schema::Reader} when an attempt to read a schema fails class ReadFailed < ReadError private def error_message "Read of #{type_string} at #{location} failed" end end # When an unregistered schema is encountered, the {JSON::Schema::Reader} is # used to fetch its contents and register it with the {JSON::Validator}. # # This default reader will read schemas from the filesystem or from a URI. class Reader # The behavior of the schema reader can be controlled by providing # callbacks to determine whether to permit reading referenced schemas. # The options +accept_uri+ and +accept_file+ should be procs which # accept a +URI+ or +Pathname+ object, and return a boolean value # indicating whether to read the referenced schema. # # URIs using the +file+ scheme will be normalized into +Pathname+ objects # and passed to the +accept_file+ callback. # # @param options [Hash] # @option options [Boolean, #call] accept_uri (true) # @option options [Boolean, #call] accept_file (true) # # @example Reject all unregistered schemas # JSON::Validator.schema_reader = JSON::Schema::Reader.new( # :accept_uri => false, # :accept_file => false # ) # # @example Only permit URIs from certain hosts # JSON::Validator.schema_reader = JSON::Schema::Reader.new( # :accept_file => false, # :accept_uri => proc { |uri| ['mycompany.com', 'json-schema.org'].include?(uri.host) } # ) def initialize(options = {}) @accept_uri = options.fetch(:accept_uri, true) @accept_file = options.fetch(:accept_file, true) end # @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 could not be read # @raise [JSON::Schema::ParseError] if the schema was not a valid JSON object # @raise [JSON::Schema::ReadFailed] if reading the location was acceptable but the # attempt to retrieve it failed def read(location) uri = JSON::Util::URI.parse(location.to_s) body = if uri.scheme.nil? || uri.scheme == 'file' uri = JSON::Util::URI.file_uri(uri) read_file(Pathname.new(uri.path).expand_path) else read_uri(uri) end JSON::Schema.new(JSON::Validator.parse(body), uri) end # @param uri [Addressable::URI] # @return [Boolean] def accept_uri?(uri) if @accept_uri.respond_to?(:call) @accept_uri.call(uri) else @accept_uri end end # @param pathname [Pathname] # @return [Boolean] def accept_file?(pathname) if @accept_file.respond_to?(:call) @accept_file.call(pathname) else @accept_file end end private def read_uri(uri) if accept_uri?(uri) open(uri.to_s).read else raise JSON::Schema::ReadRefused.new(uri.to_s, :uri) end rescue OpenURI::HTTPError, SocketError raise JSON::Schema::ReadFailed.new(uri.to_s, :uri) end def read_file(pathname) if accept_file?(pathname) File.read(JSON::Util::URI.unescaped_path(pathname.to_s)) else raise JSON::Schema::ReadRefused.new(pathname.to_s, :file) end rescue Errno::ENOENT raise JSON::Schema::ReadFailed.new(pathname.to_s, :file) end end end end ruby-json-schema-2.8.1/lib/json-schema/schema/validator.rb000066400000000000000000000022401341167564500234510ustar00rootroot00000000000000module JSON class Schema class Validator attr_accessor :attributes, :formats, :uri, :names attr_reader :default_formats def initialize() @attributes = {} @formats = {} @default_formats = {} @uri = nil @names = [] @metaschema_name = '' end def extend_schema_definition(schema_uri) warn "[DEPRECATION NOTICE] The preferred way to extend a Validator is by subclassing, rather than #extend_schema_definition. This method will be removed in version >= 3." validator = JSON::Validator.validator_for_uri(schema_uri) @attributes.merge!(validator.attributes) end def validate(current_schema, data, fragments, processor, options = {}) current_schema.schema.each do |attr_name,attribute| if @attributes.has_key?(attr_name.to_s) @attributes[attr_name.to_s].validate(current_schema, data, fragments, processor, self, options) end end data end def metaschema resources = File.expand_path('../../../../resources', __FILE__) File.join(resources, @metaschema_name) end end end end ruby-json-schema-2.8.1/lib/json-schema/util/000077500000000000000000000000001341167564500206565ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/util/array_set.rb000066400000000000000000000010111341167564500231650ustar00rootroot00000000000000require 'set' # This is a hack that I don't want to ever use anywhere else or repeat EVER, but we need enums to be # an Array to pass schema validation. But we also want fast lookup! class ArraySet < Array def include?(obj) if !defined? @values @values = Set.new self.each { |x| @values << convert_to_float_if_numeric(x) } end @values.include?(convert_to_float_if_numeric(obj)) end private def convert_to_float_if_numeric(value) value.is_a?(Numeric) ? value.to_f : value end end ruby-json-schema-2.8.1/lib/json-schema/util/uri.rb000066400000000000000000000054301341167564500220040ustar00rootroot00000000000000require 'addressable/uri' 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, 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 = file_uri(data) end @normalize_cache[uri] = normalized_uri.freeze end normalized_uri end def self.absolutize_ref(ref, base) ref_uri = strip_fragment(ref.dup) return ref_uri if ref_uri.absolute? return parse(base) if ref_uri.path.empty? uri = strip_fragment(base.dup).join(ref_uri.path) normalized_uri(uri) end def self.normalize_ref(ref, base) ref_uri = parse(ref) base_uri = parse(base) ref_uri.defer_validation do if ref_uri.relative? ref_uri.merge!(base_uri) # Check for absolute path path, fragment = ref.to_s.split("#") if path.nil? || path == '' ref_uri.path = base_uri.path elsif path[0,1] == "/" ref_uri.path = Pathname.new(path).cleanpath.to_s else ref_uri.join!(path) end ref_uri.fragment = fragment end ref_uri.fragment = "" if ref_uri.fragment.nil? || ref_uri.fragment.empty? end ref_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 rescue Addressable::URI::InvalidURIError => e raise JSON::Schema::UriError.new(e.message) end def self.strip_fragment(uri) parsed_uri = parse(uri) if parsed_uri.fragment.nil? || parsed_uri.fragment.empty? parsed_uri else 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.unescape_uri(uri) Addressable::URI.unescape(uri) end def self.unescaped_path(uri) parsed_uri = parse(uri) Addressable::URI.unescape(parsed_uri.path) end def self.clear_cache @parse_cache = {} @normalize_cache = {} end end end end ruby-json-schema-2.8.1/lib/json-schema/util/uuid.rb000066400000000000000000000204271341167564500221560ustar00rootroot00000000000000#!/usr/bin/env ruby ### http://mput.dip.jp/mput/uuid.txt # Copyright(c) 2005 URABE, Shyouhei. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this code, to deal in the code without restriction, including without # limitation the rights to use, copy, modify, merge, publish, distribute, # sublicense, and/or sell copies of the code, and to permit persons to whom the # code is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the code. # # THE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE CODE OR THE USE OR OTHER DEALINGS IN THE # CODE. # # 2009-02-20: Modified by Pablo Lorenzoni to correctly # include the version in the raw_bytes. require 'digest/md5' require 'digest/sha1' require 'tmpdir' module JSON module Util # Pure ruby UUID generator, which is compatible with RFC4122 UUID = Struct.new :raw_bytes class UUID private_class_method :new class << self def mask19 v, str # :nodoc nstr = str.bytes.to_a version = [0, 16, 32, 48, 64, 80][v] nstr[6] &= 0b00001111 nstr[6] |= version # nstr[7] &= 0b00001111 # nstr[7] |= 0b01010000 nstr[8] &= 0b00111111 nstr[8] |= 0b10000000 str = '' nstr.each { |s| str << s.chr } str end def mask18 v, str # :nodoc version = [0, 16, 32, 48, 64, 80][v] str[6] &= 0b00001111 str[6] |= version # str[7] &= 0b00001111 # str[7] |= 0b01010000 str[8] &= 0b00111111 str[8] |= 0b10000000 str end def mask v, str if RUBY_VERSION >= "1.9.0" return mask19 v, str else return mask18 v, str end end private :mask, :mask18, :mask19 # UUID generation using SHA1. Recommended over create_md5. # Namespace object is another UUID, some of them are pre-defined below. def create_sha1 str, namespace sha1 = Digest::SHA1.new sha1.update namespace.raw_bytes sha1.update str sum = sha1.digest raw = mask 5, sum[0..15] ret = new raw ret.freeze ret end alias :create_v5 :create_sha1 # UUID generation using MD5 (for backward compat.) def create_md5 str, namespace md5 = Digest::MD5.new md5.update namespace.raw_bytes md5.update str sum = md5.digest raw = mask 3, sum[0..16] ret = new raw ret.freeze ret end alias :create_v3 :create_md5 # UUID generation using random-number generator. From it's random # nature, there's no warranty that the created ID is really universaly # unique. def create_random rnd = [ rand(0x100000000), rand(0x100000000), rand(0x100000000), rand(0x100000000), ].pack "N4" raw = mask 4, rnd ret = new raw ret.freeze ret end alias :create_v4 :create_random def read_state fp # :nodoc: fp.rewind Marshal.load fp.read end def write_state fp, c, m # :nodoc: fp.rewind str = Marshal.dump [c, m] fp.write str end private :read_state, :write_state STATE_FILE = 'ruby-uuid' # create the "version 1" UUID with current system clock, current UTC # timestamp, and the IEEE 802 address (so-called MAC address). # # Speed notice: it's slow. It writes some data into hard drive on every # invokation. If you want to speed this up, try remounting tmpdir with a # memory based filesystem (such as tmpfs). STILL slow? then no way but # rewrite it with c :) def create clock=nil, time=nil, mac_addr=nil c = t = m = nil Dir.chdir Dir.tmpdir do unless FileTest.exist? STATE_FILE then # Generate a pseudo MAC address because we have no pure-ruby way # to know the MAC address of the NIC this system uses. Note # that cheating with pseudo arresses here is completely legal: # see Section 4.5 of RFC4122 for details. sha1 = Digest::SHA1.new 256.times do r = [rand(0x100000000)].pack "N" sha1.update r end str = sha1.digest r = rand 14 # 20-6 node = str[r, 6] || str if RUBY_VERSION >= "1.9.0" nnode = node.bytes.to_a nnode[0] |= 0x01 node = '' nnode.each { |s| node << s.chr } else node[0] |= 0x01 # multicast bit end k = rand 0x40000 open STATE_FILE, 'w' do |fp| fp.flock IO::LOCK_EX write_state fp, k, node fp.chmod 0o777 # must be world writable end end open STATE_FILE, 'r+' do |fp| fp.flock IO::LOCK_EX c, m = read_state fp c = clock % 0x4000 if clock m = mac_addr if mac_addr t = time if t.nil? then # UUID epoch is 1582/Oct/15 tt = Time.now t = tt.to_i*10000000 + tt.tv_usec*10 + 0x01B21DD213814000 end c = c.succ # important; increment here write_state fp, c, m end end tl = t & 0xFFFF_FFFF tm = t >> 32 tm = tm & 0xFFFF th = t >> 48 th = th & 0x0FFF th = th | 0x1000 cl = c & 0xFF ch = c & 0x3F00 ch = ch >> 8 ch = ch | 0x80 pack tl, tm, th, cl, ch, m end alias :create_v1 :create # A simple GUID parser: just ignores unknown characters and convert # hexadecimal dump into 16-octet object. def parse obj str = obj.to_s.sub %r/\Aurn:uuid:/, '' str.gsub! %r/[^0-9A-Fa-f]/, '' raw = str[0..31].lines.to_a.pack 'H*' ret = new raw ret.freeze ret end # The 'primitive constructor' of this class # Note UUID.pack(uuid.unpack) == uuid def pack tl, tm, th, ch, cl, n raw = [tl, tm, th, ch, cl, n].pack "NnnCCa6" ret = new raw ret.freeze ret end end # The 'primitive deconstructor', or the dual to pack. # Note UUID.pack(uuid.unpack) == uuid def unpack raw_bytes.unpack "NnnCCa6" end # Generate the string representation (a.k.a GUID) of this UUID def to_s a = unpack tmp = a[-1].unpack 'C*' a[-1] = sprintf '%02x%02x%02x%02x%02x%02x', *tmp "%08x-%04x-%04x-%02x%02x-%s" % a end alias guid to_s # Convert into a RFC4122-comforming URN representation def to_uri "urn:uuid:" + self.to_s end alias urn to_uri # Convert into 128-bit unsigned integer def to_int tmp = self.raw_bytes.unpack "C*" tmp.inject do |r, i| r * 256 | i end end alias to_i to_int # Gets the version of this UUID # returns nil if bad version def version a = unpack v = (a[2] & 0xF000).to_s(16)[0].chr.to_i return v if (1..5).include? v return nil end # Two UUIDs are said to be equal if and only if their (byte-order # canonicalized) integer representations are equivallent. Refer RFC4122 for # details. def == other to_i == other.to_i end include Comparable # UUIDs are comparable (don't know what benefits are there, though). def <=> other to_s <=> other.to_s end # Pre-defined UUID Namespaces described in RFC4122 Appendix C. NameSpace_DNS = parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8" NameSpace_URL = parse "6ba7b811-9dad-11d1-80b4-00c04fd430c8" NameSpace_OID = parse "6ba7b812-9dad-11d1-80b4-00c04fd430c8" NameSpace_X500 = parse "6ba7b814-9dad-11d1-80b4-00c04fd430c8" # The Nil UUID in RFC4122 Section 4.1.7 Nil = parse "00000000-0000-0000-0000-000000000000" end end endruby-json-schema-2.8.1/lib/json-schema/validator.rb000066400000000000000000000466461341167564500222330ustar00rootroot00000000000000require 'open-uri' require 'pathname' require 'bigdecimal' require 'digest/sha1' require 'date' require 'thread' require 'yaml' 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' require 'json-schema/util/uri' module JSON class Validator @@schemas = {} @@cache_schemas = true @@default_opts = { :list => false, :version => nil, :validate_schema => false, :record_errors => false, :errors_as_objects => false, :insert_defaults => false, :clear_cache => false, :strict => false, :parse_data => true } @@validators = {} @@default_validator = nil @@available_json_backends = [] @@json_backend = nil @@serializer = nil @@mutex = Mutex.new def initialize(schema_data, data, opts={}) @options = @@default_opts.clone.merge(opts) @errors = [] validator = self.class.validator_for_name(@options[:version]) @options[:version] = validator @options[:schema_reader] ||= self.class.schema_reader @validation_options = @options[:record_errors] ? {:record_errors => true} : {} @validation_options[:insert_defaults] = true if @options[:insert_defaults] @validation_options[:strict] = true if @options[:strict] == true @validation_options[:clear_cache] = true if !@@cache_schemas || @options[:clear_cache] @@mutex.synchronize { @base_schema = initialize_schema(schema_data) } @original_data = data @data = initialize_data(data) @@mutex.synchronize { build_schemas(@base_schema) } # validate the schema, if requested if @options[:validate_schema] if @base_schema.schema["$schema"] base_validator = self.class.validator_for_name(@base_schema.schema["$schema"]) end metaschema = base_validator ? base_validator.metaschema : validator.metaschema # Don't clear the cache during metaschema validation! self.class.validate!(metaschema, @base_schema.schema, {:clear_cache => false}) end # If the :fragment option is set, try and validate against the fragment if opts[:fragment] @base_schema = schema_from_fragment(@base_schema, opts[:fragment]) end end def schema_from_fragment(base_schema, fragment) schema_uri = base_schema.uri fragments = fragment.split("/") # ensure the first element was a hash, per the fragment spec if fragments.shift != "#" raise JSON::Schema::SchemaError.new("Invalid fragment syntax in :fragment option") end fragments.each do |f| if base_schema.is_a?(JSON::Schema) #test if fragment is a JSON:Schema instance if !base_schema.schema.has_key?(f) raise JSON::Schema::SchemaError.new("Invalid fragment resolution for :fragment option") end base_schema = base_schema.schema[f] elsif base_schema.is_a?(Hash) if !base_schema.has_key?(f) raise JSON::Schema::SchemaError.new("Invalid fragment resolution for :fragment option") end base_schema = JSON::Schema.new(base_schema[f],schema_uri,@options[:version]) elsif base_schema.is_a?(Array) if base_schema[f.to_i].nil? raise JSON::Schema::SchemaError.new("Invalid fragment resolution for :fragment option") end base_schema = JSON::Schema.new(base_schema[f.to_i],schema_uri,@options[:version]) else raise JSON::Schema::SchemaError.new("Invalid schema encountered when resolving :fragment option") end end if @options[:list] base_schema.to_array_schema elsif base_schema.is_a?(Hash) JSON::Schema.new(base_schema, schema_uri, @options[:version]) else base_schema end end # Run a simple true/false validation of data against a schema def validate @base_schema.validate(@data,[],self,@validation_options) if @options[:record_errors] if @options[:errors_as_objects] @errors.map{|e| e.to_hash} else @errors.map{|e| e.to_string} end else true end ensure if @validation_options[:clear_cache] == true self.class.clear_cache end if @validation_options[:insert_defaults] self.class.merge_missing_values(@data, @original_data) end end def load_ref_schema(parent_schema, ref) schema_uri = JSON::Util::URI.absolutize_ref(ref, parent_schema.uri) return true if self.class.schema_loaded?(schema_uri) validator = self.class.validator_for_uri(schema_uri, false) schema_uri = JSON::Util::URI.file_uri(validator.metaschema) if validator schema = @options[:schema_reader].read(schema_uri) self.class.add_schema(schema) build_schemas(schema) end # Build all schemas with IDs, mapping out the namespace def build_schemas(parent_schema) schema = parent_schema.schema # Build ref schemas if they exist if schema["$ref"] load_ref_schema(parent_schema, schema["$ref"]) end case schema["extends"] when String load_ref_schema(parent_schema, schema["extends"]) when Array schema['extends'].each do |type| handle_schema(parent_schema, type) end end # Check for schemas in union types ["type", "disallow"].each do |key| if schema[key].is_a?(Array) schema[key].each do |type| if type.is_a?(Hash) handle_schema(parent_schema, type) end end end end # Schema properties whose values are objects, the values of which # are themselves schemas. %w[definitions properties patternProperties].each do |key| next unless value = schema[key] value.each do |k, inner_schema| handle_schema(parent_schema, inner_schema) end end # Schema properties whose values are themselves schemas. %w[additionalProperties additionalItems dependencies extends].each do |key| next unless schema[key].is_a?(Hash) handle_schema(parent_schema, schema[key]) end # Schema properties whose values may be an array of schemas. %w[allOf anyOf oneOf not].each do |key| next unless value = schema[key] Array(value).each do |inner_schema| handle_schema(parent_schema, inner_schema) end end # Items are always schemas if schema["items"] items = schema["items"].clone items = [items] unless items.is_a?(Array) items.each do |item| handle_schema(parent_schema, item) end end # Convert enum to a ArraySet if schema["enum"].is_a?(Array) schema["enum"] = ArraySet.new(schema["enum"]) end end # 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.dup schema = JSON::Schema.new(obj, schema_uri, parent_schema.validator) if obj['id'] self.class.add_schema(schema) end build_schemas(schema) end end def validation_error(error) @errors.push(error) end def validation_errors @errors end class << self def validate(schema, data,opts={}) begin validate!(schema, data, opts) rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError return false end end def validate_json(schema, data, opts={}) validate(schema, data, opts.merge(:json => true)) end def validate_uri(schema, data, opts={}) validate(schema, data, opts.merge(:uri => true)) end def validate!(schema, data,opts={}) validator = new(schema, data, opts) validator.validate end def validate2(schema, data, opts={}) warn "[DEPRECATION NOTICE] JSON::Validator#validate2 has been replaced by JSON::Validator#validate! and will be removed in version >= 3. Please use the #validate! method instead." validate!(schema, data, opts) end def validate_json!(schema, data, opts={}) validate!(schema, data, opts.merge(:json => true)) end def validate_uri!(schema, data, opts={}) validate!(schema, data, opts.merge(:uri => true)) end def fully_validate(schema, data, opts={}) validate!(schema, data, opts.merge(:record_errors => true)) end def fully_validate_schema(schema, opts={}) data = schema schema = validator_for_name(opts[:version]).metaschema fully_validate(schema, data, opts) end def fully_validate_json(schema, data, opts={}) fully_validate(schema, data, opts.merge(:json => true)) end def fully_validate_uri(schema, data, opts={}) fully_validate(schema, data, opts.merge(:uri => true)) end def schema_reader @@schema_reader ||= JSON::Schema::Reader.new end def schema_reader=(reader) @@schema_reader = reader end def clear_cache @@schemas = {} JSON::Util::URI.clear_cache end def schemas @@schemas end def add_schema(schema) @@schemas[schema_key_for(schema.uri)] ||= schema end def schema_for_uri(uri) # We only store normalized uris terminated with fragment #, so we can try whether # normalization can be skipped @@schemas[uri] || @@schemas[schema_key_for(uri)] end def schema_loaded?(schema_uri) !schema_for_uri(schema_uri).nil? end def schema_key_for(uri) key = Util::URI.normalized_uri(uri).to_s key.end_with?('#') ? key : "#{key}#" end def cache_schemas=(val) warn "[DEPRECATION NOTICE] Schema caching is now a validation option. Schemas will still be cached if this is set to true, but this method will be removed in version >= 3. Please use the :clear_cache validation option instead." @@cache_schemas = val == true ? true : false end def validators @@validators end def default_validator @@default_validator end def validator_for_uri(schema_uri, raise_not_found=true) return default_validator unless schema_uri u = JSON::Util::URI.parse(schema_uri) validator = validators["#{u.scheme}://#{u.host}#{u.path}"] if validator.nil? && raise_not_found raise JSON::Schema::SchemaError.new("Schema not found: #{schema_uri}") else validator end end def validator_for_name(schema_name, raise_not_found=true) return default_validator unless schema_name schema_name = schema_name.to_s validator = validators.values.detect do |v| Array(v.names).include?(schema_name) end if validator.nil? && raise_not_found raise JSON::Schema::SchemaError.new("The requested JSON schema version is not supported") else validator end end def validator_for(schema_uri) warn "[DEPRECATION NOTICE] JSON::Validator#validator_for has been replaced by JSON::Validator#validator_for_uri and will be removed in version >= 3. Please use the #validator_for_uri method instead." validator_for_uri(schema_uri) end def register_validator(v) @@validators["#{v.uri.scheme}://#{v.uri.host}#{v.uri.path}"] = v end def register_default_validator(v) @@default_validator = v end def register_format_validator(format, validation_proc, versions = (@@validators.flat_map{ |k, v| v.names.first } + [nil])) custom_format_validator = JSON::Schema::CustomFormat.new(validation_proc) versions.each do |version| validator = validator_for_name(version) validator.formats[format.to_s] = custom_format_validator end end def deregister_format_validator(format, versions = (@@validators.flat_map{ |k, v| v.names.first } + [nil])) versions.each do |version| validator = validator_for_name(version) validator.formats[format.to_s] = validator.default_formats[format.to_s] end end def restore_default_formats(versions = (@@validators.flat_map{ |k, v| v.names.first } + [nil])) versions.each do |version| validator = validator_for_name(version) validator.formats = validator.default_formats.clone 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 end def merge_missing_values(source, destination) case destination when Hash source.each do |key, source_value| destination_value = destination[key] || destination[key.to_sym] if destination_value.nil? destination[key] = source_value else merge_missing_values(source_value, destination_value) end end when Array source.each_with_index do |source_value, i| destination_value = destination[i] merge_missing_values(source_value, destination_value) end end end if !defined?(MultiJson) if Gem::Specification::find_all_by_name('json').any? require 'json' @@available_json_backends << 'json' @@json_backend = 'json' else # Try force-loading json for rubies > 1.9.2 begin require 'json' @@available_json_backends << 'json' @@json_backend = 'json' rescue LoadError end end if Gem::Specification::find_all_by_name('yajl-ruby').any? require 'yajl' @@available_json_backends << 'yajl' @@json_backend = 'yajl' end 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 end end private if Gem::Specification::find_all_by_name('uuidtools').any? require 'uuidtools' @@fake_uuid_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s } else require 'json-schema/util/uuid' @@fake_uuid_generator = lambda{|s| JSON::Util::UUID.create_v5(s,JSON::Util::UUID::Nil).to_s } end def serialize schema if defined?(MultiJson) MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema) else @@serializer.call(schema) end end def fake_uuid schema @@fake_uuid_generator.call(schema) end def initialize_schema(schema) if schema.is_a?(String) begin # Build a fake URI for this schema_uri = JSON::Util::URI.parse(fake_uuid(schema)) schema = JSON::Schema.new(self.class.parse(schema), schema_uri, @options[:version]) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema end self.class.add_schema(schema) rescue JSON::Schema::JsonParseError # Build a uri for it schema_uri = Util::URI.normalized_uri(schema) if !self.class.schema_loaded?(schema_uri) schema = @options[:schema_reader].read(schema_uri) schema = JSON::Schema.stringify(schema) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema end self.class.add_schema(schema) else schema = self.class.schema_for_uri(schema_uri) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema schema.uri = JSON::Util::URI.parse(fake_uuid(serialize(schema.schema))) self.class.add_schema(schema) end schema end end elsif schema.is_a?(Hash) 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? schema = schema.to_array_schema end self.class.add_schema(schema) else raise JSON::Schema::SchemaParseError, "Invalid schema - must be either a string or a hash" end schema end def initialize_data(data) if @options[:parse_data] if @options[:json] data = self.class.parse(data) elsif @options[:uri] json_uri = Util::URI.normalized_uri(data) data = self.class.parse(custom_open(json_uri)) elsif data.is_a?(String) begin data = self.class.parse(data) rescue JSON::Schema::JsonParseError begin json_uri = Util::URI.normalized_uri(data) data = self.class.parse(custom_open(json_uri)) rescue JSON::Schema::JsonLoadError, JSON::Schema::UriError # Silently discard the error - use the data as-is end end end end JSON::Schema.stringify(data) end def custom_open(uri) uri = Util::URI.normalized_uri(uri) if uri.is_a?(String) 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 begin File.read(JSON::Util::URI.unescaped_path(uri)) rescue SystemCallError => e raise JSON::Schema::JsonLoadError, e.message end end end end end ruby-json-schema-2.8.1/lib/json-schema/validators/000077500000000000000000000000001341167564500220515ustar00rootroot00000000000000ruby-json-schema-2.8.1/lib/json-schema/validators/draft1.rb000066400000000000000000000031241341167564500235570ustar00rootroot00000000000000require 'json-schema/schema/validator' module JSON class Schema class Draft1 < Validator def initialize super @attributes = { "type" => JSON::Schema::TypeAttribute, "disallow" => JSON::Schema::DisallowAttribute, "format" => JSON::Schema::FormatAttribute, "maximum" => JSON::Schema::MaximumInclusiveAttribute, "minimum" => JSON::Schema::MinimumInclusiveAttribute, "minItems" => JSON::Schema::MinItemsAttribute, "maxItems" => JSON::Schema::MaxItemsAttribute, "minLength" => JSON::Schema::MinLengthAttribute, "maxLength" => JSON::Schema::MaxLengthAttribute, "maxDecimal" => JSON::Schema::MaxDecimalAttribute, "enum" => JSON::Schema::EnumAttribute, "properties" => JSON::Schema::PropertiesOptionalAttribute, "pattern" => JSON::Schema::PatternAttribute, "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute, "items" => JSON::Schema::ItemsAttribute, "extends" => JSON::Schema::ExtendsAttribute } @default_formats = { 'date-time' => DateTimeFormat, 'date' => DateFormat, 'time' => TimeFormat, 'ip-address' => IP4Format, 'ipv6' => IP6Format, 'uri' => UriFormat } @formats = @default_formats.clone @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 ruby-json-schema-2.8.1/lib/json-schema/validators/draft2.rb000066400000000000000000000032251341167564500235620ustar00rootroot00000000000000require 'json-schema/schema/validator' module JSON class Schema class Draft2 < Validator def initialize super @attributes = { "type" => JSON::Schema::TypeAttribute, "disallow" => JSON::Schema::DisallowAttribute, "format" => JSON::Schema::FormatAttribute, "maximum" => JSON::Schema::MaximumInclusiveAttribute, "minimum" => JSON::Schema::MinimumInclusiveAttribute, "minItems" => JSON::Schema::MinItemsAttribute, "maxItems" => JSON::Schema::MaxItemsAttribute, "uniqueItems" => JSON::Schema::UniqueItemsAttribute, "minLength" => JSON::Schema::MinLengthAttribute, "maxLength" => JSON::Schema::MaxLengthAttribute, "divisibleBy" => JSON::Schema::DivisibleByAttribute, "enum" => JSON::Schema::EnumAttribute, "properties" => JSON::Schema::PropertiesOptionalAttribute, "pattern" => JSON::Schema::PatternAttribute, "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute, "items" => JSON::Schema::ItemsAttribute, "extends" => JSON::Schema::ExtendsAttribute } @default_formats = { 'date-time' => DateTimeFormat, 'date' => DateFormat, 'time' => TimeFormat, 'ip-address' => IP4Format, 'ipv6' => IP6Format, 'uri' => UriFormat } @formats = @default_formats.clone @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 ruby-json-schema-2.8.1/lib/json-schema/validators/draft3.rb000066400000000000000000000036511341167564500235660ustar00rootroot00000000000000require 'json-schema/schema/validator' module JSON class Schema class Draft3 < Validator def initialize super @attributes = { "type" => JSON::Schema::TypeAttribute, "disallow" => JSON::Schema::DisallowAttribute, "format" => JSON::Schema::FormatAttribute, "maximum" => JSON::Schema::MaximumAttribute, "minimum" => JSON::Schema::MinimumAttribute, "minItems" => JSON::Schema::MinItemsAttribute, "maxItems" => JSON::Schema::MaxItemsAttribute, "uniqueItems" => JSON::Schema::UniqueItemsAttribute, "minLength" => JSON::Schema::MinLengthAttribute, "maxLength" => JSON::Schema::MaxLengthAttribute, "divisibleBy" => JSON::Schema::DivisibleByAttribute, "enum" => JSON::Schema::EnumAttribute, "properties" => JSON::Schema::PropertiesAttribute, "pattern" => JSON::Schema::PatternAttribute, "patternProperties" => JSON::Schema::PatternPropertiesAttribute, "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute, "items" => JSON::Schema::ItemsAttribute, "additionalItems" => JSON::Schema::AdditionalItemsAttribute, "dependencies" => JSON::Schema::DependenciesAttribute, "extends" => JSON::Schema::ExtendsAttribute, "$ref" => JSON::Schema::RefAttribute } @default_formats = { 'date-time' => DateTimeFormat, 'date' => DateFormat, 'ip-address' => IP4Format, 'ipv6' => IP6Format, 'time' => TimeFormat, 'uri' => UriFormat } @formats = @default_formats.clone @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 ruby-json-schema-2.8.1/lib/json-schema/validators/draft4.rb000066400000000000000000000044531341167564500235700ustar00rootroot00000000000000require 'json-schema/schema/validator' module JSON class Schema class Draft4 < Validator def initialize super @attributes = { "type" => JSON::Schema::TypeV4Attribute, "allOf" => JSON::Schema::AllOfAttribute, "anyOf" => JSON::Schema::AnyOfAttribute, "oneOf" => JSON::Schema::OneOfAttribute, "not" => JSON::Schema::NotAttribute, "disallow" => JSON::Schema::DisallowAttribute, "format" => JSON::Schema::FormatAttribute, "maximum" => JSON::Schema::MaximumAttribute, "minimum" => JSON::Schema::MinimumAttribute, "minItems" => JSON::Schema::MinItemsAttribute, "maxItems" => JSON::Schema::MaxItemsAttribute, "minProperties" => JSON::Schema::MinPropertiesAttribute, "maxProperties" => JSON::Schema::MaxPropertiesAttribute, "uniqueItems" => JSON::Schema::UniqueItemsAttribute, "minLength" => JSON::Schema::MinLengthAttribute, "maxLength" => JSON::Schema::MaxLengthAttribute, "multipleOf" => JSON::Schema::MultipleOfAttribute, "enum" => JSON::Schema::EnumAttribute, "properties" => JSON::Schema::PropertiesV4Attribute, "required" => JSON::Schema::RequiredAttribute, "pattern" => JSON::Schema::PatternAttribute, "patternProperties" => JSON::Schema::PatternPropertiesAttribute, "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute, "items" => JSON::Schema::ItemsAttribute, "additionalItems" => JSON::Schema::AdditionalItemsAttribute, "dependencies" => JSON::Schema::DependenciesV4Attribute, "extends" => JSON::Schema::ExtendsAttribute, "$ref" => JSON::Schema::RefAttribute } @default_formats = { 'date-time' => DateTimeV4Format, 'ipv4' => IP4Format, 'ipv6' => IP6Format, 'uri' => UriFormat } @formats = @default_formats.clone @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 JSON::Validator.register_validator(self.new) JSON::Validator.register_default_validator(self.new) end end end ruby-json-schema-2.8.1/lib/json-schema/validators/draft6.rb000066400000000000000000000044451341167564500235730ustar00rootroot00000000000000require 'json-schema/schema/validator' module JSON class Schema class Draft6 < Validator def initialize super @attributes = { "type" => JSON::Schema::TypeV4Attribute, "allOf" => JSON::Schema::AllOfAttribute, "anyOf" => JSON::Schema::AnyOfAttribute, "oneOf" => JSON::Schema::OneOfAttribute, "not" => JSON::Schema::NotAttribute, "disallow" => JSON::Schema::DisallowAttribute, "format" => JSON::Schema::FormatAttribute, "maximum" => JSON::Schema::MaximumAttribute, "minimum" => JSON::Schema::MinimumAttribute, "minItems" => JSON::Schema::MinItemsAttribute, "maxItems" => JSON::Schema::MaxItemsAttribute, "minProperties" => JSON::Schema::MinPropertiesAttribute, "maxProperties" => JSON::Schema::MaxPropertiesAttribute, "uniqueItems" => JSON::Schema::UniqueItemsAttribute, "minLength" => JSON::Schema::MinLengthAttribute, "maxLength" => JSON::Schema::MaxLengthAttribute, "multipleOf" => JSON::Schema::MultipleOfAttribute, "enum" => JSON::Schema::EnumAttribute, "properties" => JSON::Schema::PropertiesV4Attribute, "required" => JSON::Schema::RequiredAttribute, "pattern" => JSON::Schema::PatternAttribute, "patternProperties" => JSON::Schema::PatternPropertiesAttribute, "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute, "items" => JSON::Schema::ItemsAttribute, "additionalItems" => JSON::Schema::AdditionalItemsAttribute, "dependencies" => JSON::Schema::DependenciesV4Attribute, "extends" => JSON::Schema::ExtendsAttribute, "$ref" => JSON::Schema::RefAttribute } @default_formats = { 'date-time' => DateTimeV4Format, 'ipv4' => IP4Format, 'ipv6' => IP6Format, 'uri' => UriFormat } @formats = @default_formats.clone @uri = JSON::Util::URI.parse("http://json-schema.org/draft/schema#") @names = ["draft6", "http://json-schema.org/draft/schema#"] @metaschema_name = "draft-06.json" end JSON::Validator.register_validator(self.new) JSON::Validator.register_default_validator(self.new) end end end ruby-json-schema-2.8.1/lib/json-schema/validators/hyper-draft1.rb000066400000000000000000000004041341167564500247020ustar00rootroot00000000000000module JSON class Schema class HyperDraft1 < Draft1 def initialize super @uri = JSON::Util::URI.parse("http://json-schema.org/draft-01/hyper-schema#") end JSON::Validator.register_validator(self.new) end end end ruby-json-schema-2.8.1/lib/json-schema/validators/hyper-draft2.rb000066400000000000000000000004041341167564500247030ustar00rootroot00000000000000module JSON class Schema class HyperDraft2 < Draft2 def initialize super @uri = JSON::Util::URI.parse("http://json-schema.org/draft-02/hyper-schema#") end JSON::Validator.register_validator(self.new) end end end ruby-json-schema-2.8.1/lib/json-schema/validators/hyper-draft3.rb000066400000000000000000000004041341167564500247040ustar00rootroot00000000000000module JSON class Schema class HyperDraft3 < Draft3 def initialize super @uri = JSON::Util::URI.parse("http://json-schema.org/draft-03/hyper-schema#") end JSON::Validator.register_validator(self.new) end end end ruby-json-schema-2.8.1/lib/json-schema/validators/hyper-draft4.rb000066400000000000000000000004041341167564500247050ustar00rootroot00000000000000module JSON class Schema class HyperDraft4 < Draft4 def initialize super @uri = JSON::Util::URI.parse("http://json-schema.org/draft-04/hyper-schema#") end JSON::Validator.register_validator(self.new) end end end ruby-json-schema-2.8.1/lib/json-schema/validators/hyper-draft6.rb000066400000000000000000000004041341167564500247070ustar00rootroot00000000000000module JSON class Schema class HyperDraft6 < Draft6 def initialize super @uri = JSON::Util::URI.parse("http://json-schema.org/draft-06/hyper-schema#") end JSON::Validator.register_validator(self.new) end end end ruby-json-schema-2.8.1/resources/000077500000000000000000000000001341167564500167365ustar00rootroot00000000000000ruby-json-schema-2.8.1/resources/draft-01.json000066400000000000000000000047131341167564500211540ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-01/hyper-schema#", "id" : "http://json-schema.org/draft-01/schema#", "type" : "object", "properties" : { "type" : { "type" : ["string", "array"], "items" : { "type" : ["string", {"$ref" : "#"}] }, "optional" : true, "default" : "any" }, "properties" : { "type" : "object", "additionalProperties" : {"$ref" : "#"}, "optional" : true, "default" : {} }, "items" : { "type" : [{"$ref" : "#"}, "array"], "items" : {"$ref" : "#"}, "optional" : true, "default" : {} }, "optional" : { "type" : "boolean", "optional" : true, "default" : false }, "additionalProperties" : { "type" : [{"$ref" : "#"}, "boolean"], "optional" : true, "default" : {} }, "requires" : { "type" : ["string", {"$ref" : "#"}], "optional" : true }, "minimum" : { "type" : "number", "optional" : true }, "maximum" : { "type" : "number", "optional" : true }, "minimumCanEqual" : { "type" : "boolean", "optional" : true, "requires" : "minimum", "default" : true }, "maximumCanEqual" : { "type" : "boolean", "optional" : true, "requires" : "maximum", "default" : true }, "minItems" : { "type" : "integer", "optional" : true, "minimum" : 0, "default" : 0 }, "maxItems" : { "type" : "integer", "optional" : true, "minimum" : 0 }, "pattern" : { "type" : "string", "optional" : true, "format" : "regex" }, "minLength" : { "type" : "integer", "optional" : true, "minimum" : 0, "default" : 0 }, "maxLength" : { "type" : "integer", "optional" : true }, "enum" : { "type" : "array", "optional" : true, "minItems" : 1 }, "title" : { "type" : "string", "optional" : true }, "description" : { "type" : "string", "optional" : true }, "format" : { "type" : "string", "optional" : true }, "contentEncoding" : { "type" : "string", "optional" : true }, "default" : { "type" : "any", "optional" : true }, "maxDecimal" : { "type" : "integer", "optional" : true, "minimum" : 0 }, "disallow" : { "type" : ["string", "array"], "items" : {"type" : "string"}, "optional" : true }, "extends" : { "type" : [{"$ref" : "#"}, "array"], "items" : {"$ref" : "#"}, "optional" : true, "default" : {} } }, "optional" : true, "default" : {} }ruby-json-schema-2.8.1/resources/draft-02.json000066400000000000000000000052441341167564500211550ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-02/hyper-schema#", "id" : "http://json-schema.org/draft-02/schema#", "type" : "object", "properties" : { "type" : { "type" : ["string", "array"], "items" : { "type" : ["string", {"$ref" : "#"}] }, "optional" : true, "uniqueItems" : true, "default" : "any" }, "properties" : { "type" : "object", "additionalProperties" : {"$ref" : "#"}, "optional" : true, "default" : {} }, "items" : { "type" : [{"$ref" : "#"}, "array"], "items" : {"$ref" : "#"}, "optional" : true, "default" : {} }, "optional" : { "type" : "boolean", "optional" : true, "default" : false }, "additionalProperties" : { "type" : [{"$ref" : "#"}, "boolean"], "optional" : true, "default" : {} }, "requires" : { "type" : ["string", {"$ref" : "#"}], "optional" : true }, "minimum" : { "type" : "number", "optional" : true }, "maximum" : { "type" : "number", "optional" : true }, "minimumCanEqual" : { "type" : "boolean", "optional" : true, "requires" : "minimum", "default" : true }, "maximumCanEqual" : { "type" : "boolean", "optional" : true, "requires" : "maximum", "default" : true }, "minItems" : { "type" : "integer", "optional" : true, "minimum" : 0, "default" : 0 }, "maxItems" : { "type" : "integer", "optional" : true, "minimum" : 0 }, "uniqueItems" : { "type" : "boolean", "optional" : true, "default" : false }, "pattern" : { "type" : "string", "optional" : true, "format" : "regex" }, "minLength" : { "type" : "integer", "optional" : true, "minimum" : 0, "default" : 0 }, "maxLength" : { "type" : "integer", "optional" : true }, "enum" : { "type" : "array", "optional" : true, "minItems" : 1, "uniqueItems" : true }, "title" : { "type" : "string", "optional" : true }, "description" : { "type" : "string", "optional" : true }, "format" : { "type" : "string", "optional" : true }, "contentEncoding" : { "type" : "string", "optional" : true }, "default" : { "type" : "any", "optional" : true }, "divisibleBy" : { "type" : "number", "minimum" : 0, "minimumCanEqual" : false, "optional" : true, "default" : 1 }, "disallow" : { "type" : ["string", "array"], "items" : {"type" : "string"}, "optional" : true, "uniqueItems" : true }, "extends" : { "type" : [{"$ref" : "#"}, "array"], "items" : {"$ref" : "#"}, "optional" : true, "default" : {} } }, "optional" : true, "default" : {} }ruby-json-schema-2.8.1/resources/draft-03.json000066400000000000000000000074271341167564500211630ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-03/schema#", "id": "http://json-schema.org/draft-03/schema#", "type": "object", "properties": { "type": { "type": [ "string", "array" ], "items": { "type": [ "string", { "$ref": "#" } ] }, "uniqueItems": true, "default": "any" }, "properties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "patternProperties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "additionalProperties": { "type": [ { "$ref": "#" }, "boolean" ], "default": {} }, "items": { "type": [ { "$ref": "#" }, "array" ], "items": { "$ref": "#" }, "default": {} }, "additionalItems": { "type": [ { "$ref": "#" }, "boolean" ], "default": {} }, "required": { "type": "boolean", "default": false }, "dependencies": { "type": "object", "additionalProperties": { "type": [ "string", "array", { "$ref": "#" } ], "items": { "type": "string" } }, "default": {} }, "minimum": { "type": "number" }, "maximum": { "type": "number" }, "exclusiveMinimum": { "type": "boolean", "default": false }, "exclusiveMaximum": { "type": "boolean", "default": false }, "minItems": { "type": "integer", "minimum": 0, "default": 0 }, "maxItems": { "type": "integer", "minimum": 0 }, "uniqueItems": { "type": "boolean", "default": false }, "pattern": { "type": "string", "format": "regex" }, "minLength": { "type": "integer", "minimum": 0, "default": 0 }, "maxLength": { "type": "integer" }, "enum": { "type": "array", "minItems": 1, "uniqueItems": true }, "default": { "type": "any" }, "title": { "type": "string" }, "description": { "type": "string" }, "format": { "type": "string" }, "divisibleBy": { "type": "number", "minimum": 0, "exclusiveMinimum": true, "default": 1 }, "disallow": { "type": [ "string", "array" ], "items": { "type": [ "string", { "$ref": "#" } ] }, "uniqueItems": true }, "extends": { "type": [ { "$ref": "#" }, "array" ], "items": { "$ref": "#" }, "default": {} }, "id": { "type": "string", "format": "uri" }, "$ref": { "type": "string", "format": "uri" }, "$schema": { "type": "string", "format": "uri" } }, "dependencies": { "exclusiveMinimum": "minimum", "exclusiveMaximum": "maximum" }, "default": {} } ruby-json-schema-2.8.1/resources/draft-04.json000066400000000000000000000104271341167564500211560ustar00rootroot00000000000000{ "id": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#", "description": "Core schema meta-schema", "definitions": { "schemaArray": { "type": "array", "minItems": 1, "items": { "$ref": "#" } }, "positiveInteger": { "type": "integer", "minimum": 0 }, "positiveIntegerDefault0": { "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] }, "simpleTypes": { "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] }, "stringArray": { "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true } }, "type": "object", "properties": { "id": { "type": "string", "format": "uri" }, "$schema": { "type": "string", "format": "uri" }, "title": { "type": "string" }, "description": { "type": "string" }, "default": {}, "multipleOf": { "type": "number", "minimum": 0, "exclusiveMinimum": true }, "maximum": { "type": "number" }, "exclusiveMaximum": { "type": "boolean", "default": false }, "minimum": { "type": "number" }, "exclusiveMinimum": { "type": "boolean", "default": false }, "maxLength": { "$ref": "#/definitions/positiveInteger" }, "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, "pattern": { "type": "string", "format": "regex" }, "additionalItems": { "anyOf": [ { "type": "boolean" }, { "$ref": "#" } ], "default": {} }, "items": { "anyOf": [ { "$ref": "#" }, { "$ref": "#/definitions/schemaArray" } ], "default": {} }, "maxItems": { "$ref": "#/definitions/positiveInteger" }, "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, "uniqueItems": { "type": "boolean", "default": false }, "maxProperties": { "$ref": "#/definitions/positiveInteger" }, "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, "required": { "$ref": "#/definitions/stringArray" }, "additionalProperties": { "anyOf": [ { "type": "boolean" }, { "$ref": "#" } ], "default": {} }, "definitions": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "properties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "patternProperties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "dependencies": { "type": "object", "additionalProperties": { "anyOf": [ { "$ref": "#" }, { "$ref": "#/definitions/stringArray" } ] } }, "enum": { "type": "array", "minItems": 1, "uniqueItems": true }, "type": { "anyOf": [ { "$ref": "#/definitions/simpleTypes" }, { "type": "array", "items": { "$ref": "#/definitions/simpleTypes" }, "minItems": 1, "uniqueItems": true } ] }, "allOf": { "$ref": "#/definitions/schemaArray" }, "anyOf": { "$ref": "#/definitions/schemaArray" }, "oneOf": { "$ref": "#/definitions/schemaArray" }, "not": { "$ref": "#" } }, "dependencies": { "exclusiveMaximum": [ "maximum" ], "exclusiveMinimum": [ "minimum" ] }, "default": {} } ruby-json-schema-2.8.1/resources/draft-06.json000066400000000000000000000103531341167564500211560ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft/schema#", "$id": "http://json-schema.org/draft/schema#", "title": "Core schema meta-schema", "definitions": { "schemaArray": { "type": "array", "minItems": 1, "items": { "$ref": "#" } }, "positiveInteger": { "type": "integer", "minimum": 0 }, "positiveIntegerDefault0": { "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] }, "simpleTypes": { "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] }, "stringArray": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "defaultItems": [] } }, "type": ["object", "boolean"], "properties": { "$id": { "type": "string", "format": "uri-reference" }, "$schema": { "type": "string", "format": "uri" }, "$ref": { "type": "string", "format": "uri-reference" }, "title": { "type": "string" }, "description": { "type": "string" }, "default": {}, "multipleOf": { "type": "number", "exclusiveMinimum": 0 }, "maximum": { "type": "number" }, "exclusiveMaximum": { "type": "number" }, "minimum": { "type": "number" }, "exclusiveMinimum": { "type": "number" }, "maxLength": { "$ref": "#/definitions/positiveInteger" }, "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, "pattern": { "type": "string", "format": "regex" }, "additionalItems": { "$ref": "#" }, "items": { "anyOf": [ { "$ref": "#" }, { "$ref": "#/definitions/schemaArray" } ], "default": {} }, "maxItems": { "$ref": "#/definitions/positiveInteger" }, "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, "uniqueItems": { "type": "boolean", "default": false }, "contains": { "$ref": "#" }, "maxProperties": { "$ref": "#/definitions/positiveInteger" }, "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, "required": { "$ref": "#/definitions/stringArray" }, "additionalProperties": { "$ref": "#" }, "definitions": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "properties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "patternProperties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "dependencies": { "type": "object", "additionalProperties": { "anyOf": [ { "$ref": "#" }, { "$ref": "#/definitions/stringArray" } ] } }, "propertyNames": { "$ref": "#" }, "const": {}, "enum": { "type": "array", "minItems": 1, "uniqueItems": true }, "type": { "anyOf": [ { "$ref": "#/definitions/simpleTypes" }, { "type": "array", "items": { "$ref": "#/definitions/simpleTypes" }, "minItems": 1, "uniqueItems": true } ] }, "format": { "type": "string" }, "allOf": { "$ref": "#/definitions/schemaArray" }, "anyOf": { "$ref": "#/definitions/schemaArray" }, "oneOf": { "$ref": "#/definitions/schemaArray" }, "not": { "$ref": "#" } }, "default": {} } ruby-json-schema-2.8.1/test/000077500000000000000000000000001341167564500157035ustar00rootroot00000000000000ruby-json-schema-2.8.1/test/all_of_ref_schema_test.rb000066400000000000000000000022451341167564500227020ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class AllOfRefSchemaTest < Minitest::Test def schema schema_fixture_path('all_of_ref_schema.json') end def data data_fixture_path('all_of_ref_data.json') end def test_all_of_ref_schema_fails refute_valid schema, data end def test_all_of_ref_schema_succeeds assert_valid schema, %({"name": 42}) end def test_all_of_ref_subschema_errors errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true) nested_errors = errors[0][:errors] assert_equal([:allof_0], nested_errors.keys, 'should have nested errors for each allOf subschema') assert_match(/the property '#\/name' of type string did not match the following type: integer/i, nested_errors[:allof_0][0][:message]) end def test_all_of_ref_message errors = JSON::Validator.fully_validate(schema, data) expected_message = """The property '#/' of type object did not match all of the required schemas. The schema specific errors were: - allOf #0: - The property '#/name' of type string did not match the following type: integer""" assert_equal(expected_message, errors[0]) end end ruby-json-schema-2.8.1/test/any_of_ref_schema_test.rb000066400000000000000000000030741341167564500227220ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class AnyOfRefSchemaTest < Minitest::Test def schema schema_fixture_path('any_of_ref_schema.json') end def test_any_of_ref_schema assert_valid schema, data_fixture_path('any_of_ref_data.json') end def test_any_of_ref_subschema_errors data = %({"names": ["jack"]}) errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true) nested_errors = errors[0][:errors] assert_equal([:anyof_0, :anyof_1, :anyof_2], nested_errors.keys, 'should have nested errors for each anyOf subschema') assert_match(/the property '#\/names\/0' value "jack" did not match the regex 'john'/i, nested_errors[:anyof_0][0][:message]) assert_match(/the property '#\/names\/0' value "jack" did not match the regex 'jane'/i, nested_errors[:anyof_1][0][:message]) assert_match(/the property '#\/names\/0' value "jack" did not match the regex 'jimmy'/i, nested_errors[:anyof_2][0][:message]) end def test_any_of_ref_message data = %({"names": ["jack"]}) errors = JSON::Validator.fully_validate(schema, data) expected_message = """The property '#/names/0' of type string did not match one or more of the required schemas. The schema specific errors were: - anyOf #0: - The property '#/names/0' value \"jack\" did not match the regex 'john' - anyOf #1: - The property '#/names/0' value \"jack\" did not match the regex 'jane' - anyOf #2: - The property '#/names/0' value \"jack\" did not match the regex 'jimmy'""" assert_equal(expected_message, errors[0]) end end ruby-json-schema-2.8.1/test/bad_schema_ref_test.rb000066400000000000000000000025621341167564500221760ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) require 'socket' class BadSchemaRefTest < Minitest::Test def setup WebMock.allow_net_connect! end def teardown WebMock.disable_net_connect! end def test_bad_uri_ref schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "array", "items" => { "$ref" => "../google.json"} } data = [1,2,3] error = assert_raises(JSON::Schema::ReadFailed) do JSON::Validator.validate(schema,data) end expanded_path = File.expand_path("../../google.json", __FILE__) assert_equal(:file, error.type) assert_equal(expanded_path, error.location) assert_equal("Read of file at #{expanded_path} failed", error.message) end def test_bad_host_ref schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "array", "items" => { "$ref" => "http://ppcheesecheseunicornnuuuurrrrr.example.invalid/json.schema"} } data = [1,2,3] error = assert_raises(JSON::Schema::ReadFailed) do JSON::Validator.validate(schema,data) end assert_equal(:uri, error.type) assert_equal("http://ppcheesecheseunicornnuuuurrrrr.example.invalid/json.schema", error.location) assert_equal("Read of URI at http://ppcheesecheseunicornnuuuurrrrr.example.invalid/json.schema failed", error.message) end end ruby-json-schema-2.8.1/test/caching_test.rb000066400000000000000000000022231341167564500206620ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class CachingTestTest < Minitest::Test def setup @schema = Tempfile.new(['schema', '.json']) end def teardown @schema.close @schema.unlink JSON::Validator.clear_cache end def test_caching set_schema('type' => 'string') assert_valid(schema_path, 'foo', :clear_cache => false) set_schema('type' => 'number') refute_valid(schema_path, 123) end def test_clear_cache set_schema('type' => 'string') assert_valid(schema_path, 'foo', :clear_cache => true) set_schema('type' => 'number') assert_valid(schema_path, 123) end def test_cache_schemas suppress_warnings do JSON::Validator.cache_schemas = false end set_schema('type' => 'string') assert_valid(schema_path, 'foo', :clear_cache => false) set_schema('type' => 'number') assert_valid(schema_path, 123) ensure suppress_warnings do JSON::Validator.cache_schemas = true end end private def schema_path @schema.path end def set_schema(schema_definition) @schema.write(schema_definition.to_json) @schema.rewind end end ruby-json-schema-2.8.1/test/common_test_suite_test.rb000066400000000000000000000035621341167564500230350ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) require 'json' class CommonTestSuiteTest < Minitest::Test TEST_DIR = File.expand_path('../test-suite/tests', __FILE__) IGNORED_TESTS = YAML.load_file(File.expand_path('../support/test_suite_ignored_tests.yml', __FILE__)) def setup Dir["#{TEST_DIR}/../remotes/**/*.json"].each do |path| schema = path.sub(%r{^.*/remotes/}, '') stub_request(:get, "http://localhost:1234/#{schema}"). to_return(:body => File.read(path), :status => 200) end end def self.skip?(current_test, file_path) skipped_in_file = file_path.chomp('.json').split('/').inject(IGNORED_TESTS) do |ignored, path_component| ignored.nil? ? nil : ignored[path_component] end !skipped_in_file.nil? && (skipped_in_file == :all || skipped_in_file.include?(current_test)) end Dir["#{TEST_DIR}/*"].each do |suite| version = File.basename(suite).to_sym Dir["#{suite}/**/*.json"].each do |tfile| test_list = JSON.parse(File.read(tfile)) rel_file = tfile[TEST_DIR.length+1..-1] test_list.each do |test| schema = test["schema"] base_description = test["description"] test["tests"].each do |t| full_description = "#{base_description}/#{t['description']}" next if rel_file.include?('/optional/') && skip?(full_description, rel_file) err_id = "#{rel_file}: #{full_description}" define_method("test_#{err_id}") do skip if self.class.skip?(full_description, rel_file) errors = JSON::Validator.fully_validate(schema, t["data"], :parse_data => false, :validate_schema => true, :version => version ) assert_equal t["valid"], errors.empty?, "Common test suite case failed: #{err_id}" end end end end end end ruby-json-schema-2.8.1/test/custom_format_test.rb000066400000000000000000000126321341167564500221550ustar00rootroot00000000000000# encoding: utf-8 require File.expand_path('../support/test_helper', __FILE__) class CustomFormatTest < Minitest::Test def setup @all_versions = ['draft1', 'draft2', 'draft3', 'draft4', 'draft6', nil] @format_proc = lambda { |value| raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" } @schema_6 = { "$schema" => "http://json-schema.org/draft/schema#", "properties" => { "a" => { "type" => "string", "format" => "custom", }, } } @schema_4 = @schema_6.clone @schema_4["$schema"] = "http://json-schema.org/draft-04/schema#" @schema_3 = @schema_6.clone @schema_3["$schema"] = "http://json-schema.org/draft-03/schema#" @schema_2 = @schema_6.clone @schema_2["$schema"] = "http://json-schema.org/draft-02/schema#" @schema_1 = @schema_6.clone @schema_1["$schema"] = "http://json-schema.org/draft-01/schema#" @default = @schema_6.clone @default.delete("$schema") @schemas = { "draft1" => @schema_1, "draft2" => @schema_2, "draft3" => @schema_3, "draft4" => @schema_4, "draft6" => @schema_6, nil => @default, } 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 || '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 || '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 || '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 || '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 || '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 || 'default'}") end end 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 || '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| data = { "a" => "23" } schema = @schemas[version] prefix = "Validation for '#{version || 'default'}'" assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with no 'custom' format validator registered") JSON::Validator.register_format_validator("custom", @format_proc, [version]) data["a"] = "42" assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with 'custom' format validator and correct data") data["a"] = "23" assert(!JSON::Validator.validate(schema, data), "#{prefix} fails with 'custom' format validator and wrong data") errors = JSON::Validator.fully_validate(schema, data) assert_equal(errors.count, 1) assert_match(/The property '#\/a' must be 42 in schema/, errors.first, "#{prefix} records format error") data["a"] = 23 errors = JSON::Validator.fully_validate(schema, data) assert_equal(errors.count, 1) assert_match(/The property '#\/a' of type integer did not match the following type: string/i, errors.first, "#{prefix} records no format error on type mismatch") end end def test_override_default_format @all_versions.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 || 'default'}'" assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds for default format with correct data") data["a"] = "no_ip6_address" assert(!JSON::Validator.validate(schema, data), "#{prefix} fails for default format and wrong data") data["a"] = "42" JSON::Validator.register_format_validator("ipv6", @format_proc, [version]) assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with overriden default format and correct data") JSON::Validator.deregister_format_validator("ipv6", [version]) data["a"] = "2001:db8:85a3:0:0:8a2e:370:7334" assert(JSON::Validator.validate(schema, data), "#{prefix} restores the default format on deregistration") end end end ruby-json-schema-2.8.1/test/data/000077500000000000000000000000001341167564500166145ustar00rootroot00000000000000ruby-json-schema-2.8.1/test/data/all_of_ref_data.json000066400000000000000000000000261341167564500225660ustar00rootroot00000000000000{ "name" : "john" } ruby-json-schema-2.8.1/test/data/any_of_ref_data.json000066400000000000000000000000761341167564500226120ustar00rootroot00000000000000{ "names" : [ "john" , "jane" , "jimmy" ] } ruby-json-schema-2.8.1/test/data/bad_data_1.json000066400000000000000000000000221341167564500214400ustar00rootroot00000000000000{ "a" : "poop" }ruby-json-schema-2.8.1/test/data/good_data_1.json000066400000000000000000000000151341167564500216440ustar00rootroot00000000000000{ "a" : 5 }ruby-json-schema-2.8.1/test/data/one_of_ref_links_data.json000066400000000000000000000002331341167564500237770ustar00rootroot00000000000000{ "links": [{ "rel" : ["self"] , "href":"http://api.example.com/api/object/3" } ,{ "rel" : ["up"] , "href":"http://api.example.com/api/object" } ] } ruby-json-schema-2.8.1/test/draft1_test.rb000066400000000000000000000055571341167564500204640ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class Draft1Test < Minitest::Test def validation_errors(schema, data, options) super(schema, data, :version => :draft1) end def exclusive_minimum { 'minimumCanEqual' => false } end def exclusive_maximum { 'maximumCanEqual' => false } end include ArrayValidation::ItemsTests include EnumValidation::General include EnumValidation::V1_V2 include NumberValidation::MinMaxTests include ObjectValidation::AdditionalPropertiesTests include StrictValidation include StringValidation::ValueTests include StringValidation::FormatTests include StringValidation::DateAndTimeFormatTests include TypeValidation::SimpleTypeTests include TypeValidation::AnyTypeTests include TypeValidation::SchemaUnionTypeTests def test_optional # Set up the default datatype schema = { "properties" => { "a" => {"type" => "string"} } } data = {} refute_valid schema, data data['a'] = "Hello" assert_valid schema, data schema = { "properties" => { "a" => {"type" => "integer", "optional" => "true"} } } data = {} assert_valid schema, data end def test_max_decimal # Set up the default datatype schema = { "properties" => { "a" => {"maxDecimal" => 2} } } data = { "a" => nil } data["a"] = 3.35 assert_valid schema, data data["a"] = 3.455 refute_valid schema, data schema["properties"]["a"]["maxDecimal"] = 0 data["a"] = 4.0 refute_valid schema, data data["a"] = 'boo' assert_valid schema, data data["a"] = 5 assert_valid schema, data end def test_disallow # Set up the default datatype schema = { "properties" => { "a" => {"disallow" => "integer"} } } data = { "a" => nil } data["a"] = 'string' assert_valid schema, data data["a"] = 5 refute_valid schema, data schema["properties"]["a"]["disallow"] = ["integer","string"] data["a"] = 'string' refute_valid schema, data data["a"] = 5 refute_valid schema, data data["a"] = false assert_valid schema, data end def test_format_datetime schema = { "type" => "object", "properties" => { "a" => {"type" => "string", "format" => "date-time"}} } assert_valid schema, {"a" => "2010-01-01T12:00:00Z"} refute_valid schema, {"a" => "2010-01-32T12:00:00Z"} refute_valid schema, {"a" => "2010-13-01T12:00:00Z"} refute_valid schema, {"a" => "2010-01-01T24:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:60:00Z"} refute_valid schema, {"a" => "2010-01-01T12:00:60Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00z"} refute_valid schema, {"a" => "2010-01-0112:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00Z\nabc"} end end ruby-json-schema-2.8.1/test/draft2_test.rb000066400000000000000000000047761341167564500204670ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class Draft2Test < Minitest::Test def validation_errors(schema, data, options) super(schema, data, :version => :draft2) end def exclusive_minimum { 'minimumCanEqual' => false } end def exclusive_maximum { 'maximumCanEqual' => false } end def multiple_of 'divisibleBy' end include ArrayValidation::ItemsTests include ArrayValidation::UniqueItemsTests include EnumValidation::General include EnumValidation::V1_V2 include NumberValidation::MinMaxTests include NumberValidation::MultipleOfTests include ObjectValidation::AdditionalPropertiesTests include StrictValidation include StringValidation::ValueTests include StringValidation::FormatTests include StringValidation::DateAndTimeFormatTests include TypeValidation::SimpleTypeTests include TypeValidation::AnyTypeTests include TypeValidation::SchemaUnionTypeTests def test_optional # Set up the default datatype schema = { "properties" => { "a" => {"type" => "string"} } } data = {} refute_valid schema, data data['a'] = "Hello" assert_valid schema, data schema = { "properties" => { "a" => {"type" => "integer", "optional" => "true"} } } data = {} assert_valid schema, data end def test_disallow # Set up the default datatype schema = { "properties" => { "a" => {"disallow" => "integer"} } } data = { "a" => nil } data["a"] = 'string' assert_valid schema, data data["a"] = 5 refute_valid schema, data schema["properties"]["a"]["disallow"] = ["integer","string"] data["a"] = 'string' refute_valid schema, data data["a"] = 5 refute_valid schema, data data["a"] = false assert_valid schema, data end def test_format_datetime schema = { "type" => "object", "properties" => { "a" => {"type" => "string", "format" => "date-time"}} } assert_valid schema, {"a" => "2010-01-01T12:00:00Z"} refute_valid schema, {"a" => "2010-01-32T12:00:00Z"} refute_valid schema, {"a" => "2010-13-01T12:00:00Z"} refute_valid schema, {"a" => "2010-01-01T24:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:60:00Z"} refute_valid schema, {"a" => "2010-01-01T12:00:60Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00z"} refute_valid schema, {"a" => "2010-01-0112:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00Z\nabc"} end end ruby-json-schema-2.8.1/test/draft3_test.rb000066400000000000000000000302011341167564500204460ustar00rootroot00000000000000# encoding: utf-8 require File.expand_path('../support/test_helper', __FILE__) class Draft3Test < Minitest::Test def validation_errors(schema, data, options) super(schema, data, :version => :draft3) end def exclusive_minimum { 'exclusiveMinimum' => true } end def exclusive_maximum { 'exclusiveMaximum' => true } end def multiple_of 'divisibleBy' end include ArrayValidation::ItemsTests include ArrayValidation::AdditionalItemsTests include ArrayValidation::UniqueItemsTests include EnumValidation::General include EnumValidation::V3_V4 include NumberValidation::MinMaxTests include NumberValidation::MultipleOfTests include ObjectValidation::AdditionalPropertiesTests include ObjectValidation::PatternPropertiesTests include StrictValidation include StringValidation::ValueTests include StringValidation::FormatTests include StringValidation::DateAndTimeFormatTests include TypeValidation::SimpleTypeTests include TypeValidation::AnyTypeTests include TypeValidation::SchemaUnionTypeTests def test_types # Set up the default datatype schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {} } } data = { "a" => nil } # Test an array of unioned-type objects that prevent additionalProperties schema["properties"]["a"] = { 'type' => 'array', 'items' => { 'type' => [ { 'type' => 'object', 'properties' => { "b" => { "type" => "integer" } } }, { 'type' => 'object', 'properties' => { "c" => { "type" => "string" } } } ], 'additionalProperties' => false } } data["a"] = [{"b" => 5}, {"c" => "foo"}] errors = JSON::Validator.fully_validate(schema, data) assert(errors.empty?, errors.join("\n")) # This should actually pass, because this matches the first schema in the union data["a"] << {"c" => false} assert_valid schema, data end def test_required # Set up the default datatype schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"required" => true} } } data = {} refute_valid schema, data data['a'] = "Hello" assert_valid schema, data schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"type" => "integer"} } } data = {} assert_valid schema, data end def test_strict_properties_required_props schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"type" => "string", "required" => true}, "b" => {"type" => "string", "required" => false} } } data = {"a" => "a"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) end def test_strict_properties_additional_props schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} }, "additionalProperties" => {"type" => "integer"} } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => 3} assert(JSON::Validator.validate(schema,data,:strict => true)) end def test_strict_properties_pattern_props schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} }, "patternProperties" => {"\\d+ taco" => {"type" => "integer"}} } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => 3} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "23 taco" => 3} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "23 taco" => "cheese"} assert(!JSON::Validator.validate(schema,data,:strict => true)) end def test_disallow # Set up the default datatype schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"disallow" => "integer"} } } data = { "a" => nil } data["a"] = 'string' assert_valid schema, data data["a"] = 5 refute_valid schema, data schema["properties"]["a"]["disallow"] = ["integer","string"] data["a"] = 'string' refute_valid schema, data data["a"] = 5 refute_valid schema, data data["a"] = false assert_valid schema, data end def test_extends schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => { "type" => "integer"} } } schema2 = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => { "maximum" => 5 } } } data = { "a" => 10 } assert_valid schema, data assert(!JSON::Validator.validate(schema2,data)) schema["extends"] = schema2 refute_valid schema, data end def test_list_option schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "required" => true} } } data = [{"a" => 1},{"a" => 2},{"a" => 3}] assert(JSON::Validator.validate(schema,data,:list => true)) refute_valid schema, data data = {"a" => 1} assert(!JSON::Validator.validate(schema,data,:list => true)) data = [{"a" => 1},{"b" => 2},{"a" => 3}] assert(!JSON::Validator.validate(schema,data,:list => true)) end def test_self_reference schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer"}, "b" => {"$ref" => "#"}} } assert_valid schema, {"a" => 5, "b" => {"b" => {"a" => 1}}} refute_valid schema, {"a" => 5, "b" => {"b" => {"a" => 'taco'}}} end def test_format_datetime schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "string", "format" => "date-time"}} } assert_valid schema, {"a" => "2010-01-01T12:00:00Z"} assert_valid schema, {"a" => "2010-01-01T12:00:00.1Z"} assert_valid schema, {"a" => "2010-01-01T12:00:00,1Z"} refute_valid schema, {"a" => "2010-01-32T12:00:00Z"} refute_valid schema, {"a" => "2010-13-01T12:00:00Z"} refute_valid schema, {"a" => "2010-01-01T24:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:60:00Z"} refute_valid schema, {"a" => "2010-01-01T12:00:60Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00z"} refute_valid schema, {"a" => "2010-01-0112:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00.1Z\nabc"} # test with a specific timezone assert_valid schema, {"a" => "2010-01-01T12:00:00+01"} assert_valid schema, {"a" => "2010-01-01T12:00:00+01:00"} assert_valid schema, {"a" => "2010-01-01T12:00:00+01:30"} assert_valid schema, {"a" => "2010-01-01T12:00:00+0234"} refute_valid schema, {"a" => "2010-01-01T12:00:00+01:"} refute_valid schema, {"a" => "2010-01-01T12:00:00+0"} # do not allow mixing Z and specific timezone refute_valid schema, {"a" => "2010-01-01T12:00:00Z+01"} refute_valid schema, {"a" => "2010-01-01T12:00:00+01Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00+01:30Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00+0Z"} # test without any timezone assert_valid schema, {"a" => "2010-01-01T12:00:00"} assert_valid schema, {"a" => "2010-01-01T12:00:00.12345"} assert_valid schema, {"a" => "2010-01-01T12:00:00,12345"} assert_valid schema, {"a" => "2010-01-01T12:00:00.12345"} end def test_format_uri data1 = {"a" => "http://gitbuh.com"} data2 = {"a" => "::boo"} data3 = {"a" => "http://ja.wikipedia.org/wiki/メインページ"} schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "string", "format" => "uri"}} } assert(JSON::Validator.validate(schema,data1)) assert(!JSON::Validator.validate(schema,data2)) assert(JSON::Validator.validate(schema,data3)) end def test_schema schema = { "$schema" => "http://json-schema.org/THIS-IS-NOT-A-SCHEMA", "type" => "object" } data = {"a" => "taco"} assert(!JSON::Validator.validate(schema, data)) schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object" } assert_valid schema, data end def test_dependency schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer"}, "b" => {"type" => "integer"} }, "dependencies" => { "a" => "b" } } data = {"a" => 1, "b" => 2} assert_valid schema, data data = {"a" => 1} refute_valid schema, data schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer"}, "b" => {"type" => "integer"}, "c" => {"type" => "integer"} }, "dependencies" => { "a" => ["b","c"] } } data = {"a" => 1, "c" => 2} refute_valid schema, data data = {"a" => 1, "b" => 2, "c" => 3} assert_valid schema, data end def test_default schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "default" => 42}, "b" => {"type" => "integer"} } } data = {:b => 2} assert_valid schema, data assert_nil(data["a"]) assert(JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_equal(42, data["a"]) assert_equal(2, data[:b]) schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "default" => 42, "required" => true}, "b" => {"type" => "integer"} } } data = {:b => 2} refute_valid schema, data assert_nil(data["a"]) assert(JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_equal(42, data["a"]) assert_equal(2, data[:b]) schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "default" => 42, "required" => true, "readonly" => true}, "b" => {"type" => "integer"} } } data = {:b => 2} refute_valid schema, data assert_nil(data["a"]) assert(!JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_nil(data["a"]) assert_equal(2, data[:b]) schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "default" => "42"}, "b" => {"type" => "integer"} } } data = {:b => 2} assert_valid schema, data assert_nil(data["a"]) assert(!JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_equal("42",data["a"]) assert_equal(2, data[:b]) end end ruby-json-schema-2.8.1/test/draft4_test.rb000066400000000000000000000416211341167564500204570ustar00rootroot00000000000000# encoding: utf-8 require File.expand_path('../support/test_helper', __FILE__) class Draft4Test < Minitest::Test def validation_errors(schema, data, options) super(schema, data, :version => :draft4) end def exclusive_minimum { 'exclusiveMinimum' => true } end def exclusive_maximum { 'exclusiveMaximum' => true } end def ipv4_format 'ipv4' end include ArrayValidation::ItemsTests include ArrayValidation::AdditionalItemsTests include ArrayValidation::UniqueItemsTests include EnumValidation::General include EnumValidation::V3_V4 include NumberValidation::MinMaxTests include NumberValidation::MultipleOfTests include ObjectValidation::AdditionalPropertiesTests include ObjectValidation::PatternPropertiesTests include StrictValidation include StringValidation::ValueTests include StringValidation::FormatTests include TypeValidation::SimpleTypeTests def test_required # Set up the default datatype schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "required" => ["a"], "properties" => { "a" => {} } } data = {} refute_valid schema, data data['a'] = "Hello" assert_valid schema, data schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"type" => "integer"} } } data = {} assert_valid schema, data end def test_min_properties schema = { 'minProperties' => 2 } assert_valid schema, {'a' => 1, 'b' => 2} assert_valid schema, {'a' => 1, 'b' => 2, 'c' => 3} refute_valid schema, {'a' => 1} refute_valid schema, {} end def test_max_properties schema = { 'maxProperties' => 2 } assert_valid schema, {'a' => 1, 'b' => 2} assert_valid schema, {'a' => 1} assert_valid schema, {} refute_valid schema, {'a' => 1, 'b' => 2, 'c' => 3} end def test_strict_properties schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} } } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) end def test_strict_properties_additional_props schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} }, "additionalProperties" => {"type" => "integer"} } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => 3} assert(JSON::Validator.validate(schema,data,:strict => true)) end def test_strict_properties_pattern_props schema = { "$schema" => "http://json-schema.org/draft-03/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} }, "patternProperties" => {"\\d+ taco" => {"type" => "integer"}} } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => 3} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "23 taco" => 3} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "23 taco" => "cheese"} assert(!JSON::Validator.validate(schema,data,:strict => true)) end def test_list_option schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "integer"} } } data = [{"a" => 1},{"a" => 2},{"a" => 3}] assert(JSON::Validator.validate(schema,data,:list => true)) refute_valid schema, data data = {"a" => 1} assert(!JSON::Validator.validate(schema,data,:list => true)) data = [{"a" => 1},{"b" => 2},{"a" => 3}] assert(!JSON::Validator.validate(schema,data,:list => true)) end def test_default_with_strict_and_anyof schema = { "anyOf" => [ { "type" => "object", "properties" => { "foo" => { "enum" => ["view", "search"], "default" => "view" } } }, { "type" => "object", "properties" => { "bar" => { "type" => "string" } } } ] } data = { "bar" => "baz" } assert(JSON::Validator.validate(schema, data, :insert_defaults => true, :strict => true)) end def test_default_with_anyof schema = { "anyOf" => [ { "type" => "object", "properties" => { "foo" => { "enum" => ["view", "search"], "default" => "view" } } }, { "type" => "object", "properties" => { "bar" => { "type" => "string" } } } ] } data = {} assert(JSON::Validator.validate(schema, data, :insert_defaults => true, :strict => true)) assert(data['foo'] == 'view') end def test_default_with_strict_and_oneof schema = { "oneOf" => [ { "type" => "object", "properties" => { "bar" => { "type" => "string" } } }, { "type" => "object", "properties" => { "foo" => { "enum" => ["view", "search"], "default" => "view" } } } ] } data = { "bar" => "baz" } assert(JSON::Validator.validate(schema, data, :insert_defaults => true, :strict => true)) assert(!data.key?('foo')) end def test_self_reference schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer"}, "b" => {"$ref" => "#"}} } assert_valid schema, {"a" => 5, "b" => {"b" => {"a" => 1}}} refute_valid schema, {"a" => 5, "b" => {"b" => {"a" => 'taco'}}} end def test_property_named_ref schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "$ref" => { "type" => "integer" } } } assert_valid schema, { "$ref" => 1 } refute_valid schema, { "$ref" => "#" } end def test_format_datetime schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "string", "format" => "date-time"}} } assert_valid schema, {"a" => "2010-01-01T12:00:00Z"} assert_valid schema, {"a" => "2010-01-01T12:00:00.1Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00,1Z"} refute_valid schema, {"a" => "2010-01-01T12:00:00+0000"} assert_valid schema, {"a" => "2010-01-01T12:00:00+00:00"} refute_valid schema, {"a" => "2010-01-32T12:00:00Z"} refute_valid schema, {"a" => "2010-13-01T12:00:00Z"} assert_valid schema, {"a" => "2010-01-01T24:00:00Z"} refute_valid schema, {"a" => "2010-01-01T12:60:00Z"} assert_valid schema, {"a" => "2010-01-01T12:00:60Z"} assert_valid schema, {"a" => "2010-01-01T12:00:00z"} refute_valid schema, {"a" => "2010-01-0112:00:00Z"} end def test_format_uri data1 = {"a" => "http://gitbuh.com"} data2 = {"a" => "::boo"} data3 = {"a" => "http://ja.wikipedia.org/wiki/メインページ"} schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "string", "format" => "uri"}} } assert(JSON::Validator.validate(schema,data1)) assert(!JSON::Validator.validate(schema,data2)) assert(JSON::Validator.validate(schema,data3)) end def test_schema schema = { "$schema" => "http://json-schema.org/THIS-IS-NOT-A-SCHEMA", "type" => "object" } data = {"a" => "taco"} assert(!JSON::Validator.validate(schema,data)) schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object" } assert_valid schema, data end def test_dependency schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer"}, "b" => {"type" => "integer"} }, "dependencies" => { "a" => ["b"] } } data = {"a" => 1, "b" => 2} assert_valid schema, data data = {"a" => 1} refute_valid schema, data schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer"}, "b" => {"type" => "integer"}, "c" => {"type" => "integer"} }, "dependencies" => { "a" => ["b","c"] } } data = {"a" => 1, "c" => 2} refute_valid schema, data data = {"a" => 1, "b" => 2, "c" => 3} assert_valid schema, data end def test_schema_dependency schema = { "type"=> "object", "properties"=> { "name"=> { "type"=> "string" }, "credit_card"=> { "type"=> "number" } }, "required"=> ["name"], "dependencies"=> { "credit_card"=> { "properties"=> { "billing_address"=> { "type"=> "string" } }, "required"=> ["billing_address"] } } } data = { "name" => "John Doe", "credit_card" => 5555555555555555 } assert(!JSON::Validator.validate(schema,data), 'test schema dependency with invalid data') data['billing_address'] = "Somewhere over the rainbow" assert(JSON::Validator.validate(schema,data), 'test schema dependency with valid data') end def test_default schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "default" => 42}, "b" => {"type" => "integer"} } } data = {:b => 2} assert_valid schema, data assert_nil(data["a"]) assert(JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_equal(42, data["a"]) assert_equal(2, data[:b]) schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "integer", "default" => 42}, "b" => {"type" => "integer"} } } data = {:b => 2} refute_valid schema, data assert_nil(data["a"]) assert(JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_equal(42, data["a"]) assert_equal(2, data[:b]) schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "integer", "default" => 42, "readonly" => true}, "b" => {"type" => "integer"} } } data = {:b => 2} refute_valid schema, data assert_nil(data["a"]) assert(!JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_nil(data["a"]) assert_equal(2, data[:b]) schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => {"type" => "integer", "default" => "42"}, "b" => {"type" => "integer"} } } data = {:b => 2} assert_valid schema, data assert_nil(data["a"]) assert(!JSON::Validator.validate(schema,data, :insert_defaults => true)) assert_equal("42",data["a"]) assert_equal(2, data[:b]) end def test_boolean_false_default schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "boolean", "default" => false}, "b" => {"type" => "integer"} } } data = {:b => 2} refute_valid schema, data assert_nil(data["a"]) assert(JSON::Validator.validate(schema, data, :insert_defaults => true)) assert_equal(false, data["a"]) assert_equal(2, data[:b]) end def test_all_of schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "allOf" => [ { "properties" => {"a" => {"type" => "string"}}, "required" => ["a"] }, { "properties" => {"b" => {"type" => "integer"}} } ] } data = {"a" => "hello", "b" => 5} assert_valid schema, data data = {"a" => "hello"} assert_valid schema, data data = {"a" => "hello", "b" => "taco"} refute_valid schema, data data = {"b" => 5} refute_valid schema, data end def test_any_of schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "anyOf" => [ { "properties" => {"a" => {"type" => "string"}}, "required" => ["a"] }, { "properties" => {"b" => {"type" => "integer"}} } ] } data = {"a" => "hello", "b" => 5} assert_valid schema, data data = {"a" => "hello"} assert_valid schema, data data = {"a" => "hello", "b" => "taco"} assert_valid schema, data data = {"b" => 5} assert_valid schema, data data = {"a" => 5, "b" => "taco"} refute_valid schema, data end def test_one_of schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "oneOf" => [ { "properties" => {"a" => {"type" => "string"}}, "required" => ["a"] }, { "properties" => {"b" => {"type" => "integer"}} } ] } data = {"a" => "hello", "b" => 5} refute_valid schema, data # This passes because b is not required, thus matches both schemas data = {"a" => "hello"} refute_valid schema, data data = {"a" => "hello", "b" => "taco"} assert_valid schema, data data = {"b" => 5} assert_valid schema, data data = {"a" => 5, "b" => "taco"} refute_valid schema, data end def test_not # Start with a simple not schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"not" => { "type" => ["string", "boolean"]}} } } data = {"a" => 1} assert_valid schema, data data = {"a" => "hi!"} refute_valid schema, data data = {"a" => true} refute_valid schema, data # Sub-schema not schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"not" => {"anyOf" => [ { "type" => ["string","boolean"] }, { "type" => "object", "properties" => { "b" => {"type" => "boolean"} } } ]} } } } data = {"a" => 1} assert_valid schema, data data = {"a" => "hi!"} refute_valid schema, data data = {"a" => true} refute_valid schema, data data = {"a" => {"b" => true}} refute_valid schema, data data = {"a" => {"b" => 5}} assert_valid schema, data end def test_not_fully_validate # Start with a simple not schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"not" => { "type" => ["string", "boolean"]}} } } data = {"a" => 1} errors = JSON::Validator.fully_validate(schema,data) assert_equal(0, errors.length) data = {"a" => "taco"} errors = JSON::Validator.fully_validate(schema,data) assert_equal(1, errors.length) end def test_definitions schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "array", "items" => { "$ref" => "#/definitions/positiveInteger"}, "definitions" => { "positiveInteger" => { "type" => "integer", "minimum" => 0, "exclusiveMinimum" => true } } } data = [1,2,3] assert_valid schema, data data = [-1,2,3] refute_valid schema, data end end ruby-json-schema-2.8.1/test/extended_schema_test.rb000066400000000000000000000034601341167564500224120ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) 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 class ExtendedSchema < JSON::Schema::Draft3 def initialize super @attributes["bitwise-and"] = BitwiseAndAttribute @names = ["http://test.com/test.json"] @uri = Addressable::URI.parse("http://test.com/test.json") @names = ["http://test.com/test.json"] end JSON::Validator.register_validator(ExtendedSchema.new) end def test_extended_schema_validation schema = { "$schema" => "http://test.com/test.json", "properties" => { "a" => { "bitwise-and" => 1 }, "b" => { "type" => "string" } } } assert_valid schema, {"a" => 1, "b" => "taco"} refute_valid schema, {"a" => 0, "b" => "taco"} refute_valid schema, {"a" => 1, "b" => 5} end def test_unextended_schema # Verify that using the original schema disregards the `bitwise-and` property schema = { "properties" => { "a" => { "bitwise-and" => 1 }, "b" => { "type" => "string" } } } assert_valid schema, {"a" => 0, "b" => "taco"} assert_valid schema, {"a" => 1, "b" => "taco"} refute_valid schema, {"a" => 1, "b" => 5} end end ruby-json-schema-2.8.1/test/extends_nested_test.rb000066400000000000000000000026241341167564500223070ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class ExtendsNestedTest < Minitest::Test ADDITIONAL_PROPERTIES = ['extends_and_additionalProperties_false_schema.json'] PATTERN_PROPERTIES = ['extends_and_patternProperties_schema.json'] ALL_SCHEMAS = ADDITIONAL_PROPERTIES + PATTERN_PROPERTIES def test_valid_outer ALL_SCHEMAS.each do |file| path = schema_fixture_path(file) assert_valid path, { "outerC" => true }, {}, "Outer defn is broken, maybe the outer extends overrode it" end end def test_valid_outer_extended ALL_SCHEMAS.each do |file| path = schema_fixture_path(file) assert_valid path, { "innerA" => true }, {}, "Extends at the root level isn't working" end end def test_valid_inner ALL_SCHEMAS.each do |file| path = schema_fixture_path(file) assert_valid path, { "outerB" => [{ "innerA" => true }] }, {}, "Extends isn't working in the array element defn" end end def test_invalid_inner ALL_SCHEMAS.each do |file| path = schema_fixture_path(file) refute_valid path, { "outerB" => [{ "whaaaaat" => true }] }, {}, "Array element defn allowing anything when it should only allow what's in inner.schema" end end def test_invalid_outer path = schema_fixture_path(ADDITIONAL_PROPERTIES) refute_valid path, { "whaaaaat" => true }, {}, "Outer defn allowing anything when it shouldn't" end end ruby-json-schema-2.8.1/test/files_test.rb000066400000000000000000000043331341167564500203740ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class FilesTest < Minitest::Test # # These tests are ONLY run if there is an appropriate JSON backend parser available # def test_schema_from_file assert_valid schema_fixture_path('good_schema_1.json'), { "a" => 5 } refute_valid schema_fixture_path('good_schema_1.json'), { "a" => "bad" } end 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_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 assert_valid schema_fixture_path('good_schema_1.json'), data_fixture_path('good_data_1.json'), :uri => true refute_valid schema_fixture_path('good_schema_1.json'), data_fixture_path('bad_data_1.json'), :uri => true end def test_file_ref assert_valid schema_fixture_path('good_schema_2.json'), { "b" => { "a" => 5 } } refute_valid schema_fixture_path('good_schema_1.json'), { "b" => { "a" => "boo" } } end def test_file_extends assert_valid schema_fixture_path('good_schema_extends1.json'), { "a" => 5 } assert_valid schema_fixture_path('good_schema_extends2.json'), { "a" => 5, "b" => { "a" => 5 } } end end ruby-json-schema-2.8.1/test/fragment_resolution_test.rb000066400000000000000000000040351341167564500233570ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class FragmentResolutionTest < Minitest::Test def test_fragment_resolution schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "required" => ["a"], "properties" => { "a" => { "type" => "object", "properties" => { "b" => {"type" => "integer" } } } } } data = {"b" => 5} refute_valid schema, data assert_valid schema, data, :fragment => "#/properties/a" assert_raises JSON::Schema::SchemaError do JSON::Validator.validate!(schema,data,:fragment => "/properties/a") end assert_raises JSON::Schema::SchemaError do JSON::Validator.validate!(schema,data,:fragment => "#/properties/b") end end def test_odd_level_fragment_resolution schema = { "foo" => { "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "integer"} } } } assert_valid schema, {"a" => 1}, :fragment => "#/foo" refute_valid schema, {}, :fragment => "#/foo" end def test_even_level_fragment_resolution schema = { "foo" => { "bar" => { "type" => "object", "required" => ["a"], "properties" => { "a" => {"type" => "integer"} } } } } assert_valid schema, {"a" => 1}, :fragment => "#/foo/bar" refute_valid schema, {}, :fragment => "#/foo/bar" end def test_array_fragment_resolution schema = { "type" => "object", "required" => ["a"], "properties" => { "a" => { "anyOf" => [ {"type" => "integer"}, {"type" => "string"} ] } } } refute_valid schema, "foo", :fragment => "#/properties/a/anyOf/0" assert_valid schema, "foo", :fragment => "#/properties/a/anyOf/1" assert_valid schema, 5, :fragment => "#/properties/a/anyOf/0" refute_valid schema, 5, :fragment => "#/properties/a/anyOf/1" end end ruby-json-schema-2.8.1/test/fragment_validation_with_ref_test.rb000066400000000000000000000032161341167564500251750ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class FragmentValidationWithRefTest < Minitest::Test def whole_schema { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "definitions" => { "post" => { "type" => "object", "properties" => { "content" => { "type" => "string" }, "author" => { "type" => "string" } } }, "posts" => { "type" => "array", "items" => { "$ref" => "#/definitions/post" } } } } end def whole_schema_with_array { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "definitions" => { "omg" => { "links" => [ { "type" => "object", "schema" => { "properties" => { "content" => { "type" => "string" }, "author" => { "type" => "string" } }, "required" => ["content", "author"] } } ] } } } end def test_validation_of_fragment data = [{"content" => "ohai", "author" => "Bob"}] assert_valid whole_schema, data, :fragment => "#/definitions/posts" end def test_validation_of_fragment_with_array data = {"content" => "ohai", "author" => "Bob"} assert_valid(whole_schema_with_array, data, :fragment => "#/definitions/omg/links/0/schema") end end ruby-json-schema-2.8.1/test/full_validation_test.rb000066400000000000000000000116231341167564500224460ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class FullValidationTest < Minitest::Test def test_full_validation data = {"b" => {"a" => 5}} schema = { "type" => "object", "required" => ["b"], "properties" => { "b" => { } } } errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) data = {"c" => 5} schema = { "type" => "object", "required" => ["b"], "properties" => { "b" => { }, "c" => { "type" => "string" } } } errors = JSON::Validator.fully_validate(schema,data) assert(errors.length == 2) end def test_full_validation_with_union_types data = {"b" => 5} schema = { "type" => "object", "properties" => { "b" => { "type" => ["null","integer"] } } } errors = JSON::Validator.fully_validate(schema,data) assert(errors.empty?) schema = { "type" => "object", "properties" => { "b" => { "type" => ["integer","null"] } } } 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", "properties" => { "b" => { "type" => [ { "type" => "object", "properties" => { "c" => {"type" => "string"} } }, { "type" => "object", "properties" => { "d" => {"type" => "integer"} } } ] } } } 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 = { "type" => "object", "required" => ["b"], "properties" => { "b" => { } } } errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert(errors.empty?) data = {"c" => 5} schema = { "type" => "object", "required" => ["b"], "properties" => { "b" => { }, "c" => { "type" => "string" } } } errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true) assert(errors.length == 2) assert(errors[0][:failed_attribute] == "Required") assert(errors[0][:fragment] == "#/") assert(errors[1][:failed_attribute] == "TypeV4") assert(errors[1][:fragment] == "#/c") end def test_full_validation_with_nested_required_properties schema = { "type" => "object", "required" => ["x"], "properties" => { "x" => { "type" => "object", "required" => ["a", "b"], "properties" => { "a" => {"type"=>"integer"}, "b" => {"type"=>"integer"}, "c" => {"type"=>"integer"}, "d" => {"type"=>"integer"}, "e" => {"type"=>"integer"}, } } } } 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] assert_equal 'Required', errors[0][:failed_attribute] assert_equal '#/x/e', errors[1][:fragment] assert_equal 'TypeV4', errors[1][:failed_attribute] end def test_full_validation_with_nested_required_propertiesin_array schema = { "type" => "object", "required" => ["x"], "properties" => { "x" => { "type" => "array", "items" => { "type" => "object", "required" => ["a", "b"], "properties" => { "a" => {"type"=>"integer"}, "b" => {"type"=>"integer"}, "c" => {"type"=>"integer"}, "d" => {"type"=>"integer"}, "e" => {"type"=>"integer"}, } } } } } 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] assert_equal 'Required', errors[0][:failed_attribute] assert_equal '#/x/1/e', errors[1][:fragment] assert_equal 'TypeV4', errors[1][:failed_attribute] end end ruby-json-schema-2.8.1/test/initialize_data_test.rb000066400000000000000000000111741341167564500224250ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class InitializeDataTest < Minitest::Test def test_parse_character_string schema = {'type' => 'string'} data = 'hello world' 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(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_integer_string schema = {'type' => 'integer'} data = '42' assert(JSON::Validator.validate(schema, data)) refute(JSON::Validator.validate(schema, data, :parse_data => false)) assert(JSON::Validator.validate(schema, data, :json => true)) assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_hash_string schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } } data = '{"a": "b"}' assert(JSON::Validator.validate(schema, data)) refute(JSON::Validator.validate(schema, data, :parse_data => false)) assert(JSON::Validator.validate(schema, data, :json => true)) assert_raises(JSON::Schema::UriError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_json_string schema = {'type' => 'string'} data = '"hello world"' assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, :parse_data => false)) assert(JSON::Validator.validate(schema, data, :json => true)) assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_plain_text_string schema = {'type' => 'string'} data = 'kapow' 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(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_valid_uri_string schema = {'type' => 'string'} data = 'http://foo.bar/' stub_request(:get, "foo.bar").to_return(:body => '"hello world"', :status => 200) 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(JSON::Validator.validate(schema, data, :uri => true)) end def test_parse_invalid_uri_string schema = {'type' => 'string'} data = 'http://foo.bar/' stub_request(:get, "foo.bar").to_timeout assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, :parse_data => false)) 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(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_invalid_scheme_string schema = {'type' => 'string'} data = 'pick one: [1, 2, 3]' 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(JSON::Schema::UriError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_integer schema = {'type' => 'integer'} data = 42 assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, :parse_data => false)) assert_raises(TypeError) { JSON::Validator.validate(schema, data, :json => true) } assert_raises(TypeError) { JSON::Validator.validate(schema, data, :uri => true) } end def test_parse_hash schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } } data = { 'a' => 'b' } assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, :parse_data => false)) assert_raises(TypeError) { JSON::Validator.validate(schema, data, :json => true) } assert_raises(TypeError) { JSON::Validator.validate(schema, data, :uri => true) } end end ruby-json-schema-2.8.1/test/list_option_test.rb000066400000000000000000000011471341167564500216350ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class ListOptionTest < Minitest::Test def test_list_option_reusing_schemas schema_hash = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "properties" => { "a" => { "type" => "integer" } } } uri = Addressable::URI.parse('http://example.com/item') schema = JSON::Schema.new(schema_hash, uri) JSON::Validator.add_schema(schema) data = {"a" => 1} assert_valid uri.to_s, data, clear_cache: false data = [{"a" => 1}] assert_valid uri.to_s, data, :list => true end end ruby-json-schema-2.8.1/test/load_ref_schema_test.rb000066400000000000000000000022061341167564500223620ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class LoadRefSchemaTest < Minitest::Test def load_other_schema JSON::Validator.add_schema(JSON::Schema.new( { '$schema' => 'http://json-schema.org/draft-04/schema#', 'type' => 'object', 'properties' => { "title" => { "type" => "string" } } }, Addressable::URI.parse("http://example.com/schema#") )) end def test_cached_schema schema_url = "http://example.com/schema#" schema = { "$ref" => schema_url } data = {} load_other_schema _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" } data = {} load_other_schema _validator = JSON::Validator.new(schema, data) assert JSON::Validator.schema_loaded?(schema_url) end def test_metaschema schema = { "$ref" => "http://json-schema.org/draft-04/schema#" } data = {} assert_valid schema, data end end ruby-json-schema-2.8.1/test/merge_missing_values_test.rb000066400000000000000000000033411341167564500234770ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class MergeMissingValuesTest < Minitest::Test def test_merge_missing_values_for_string original = 'foo' updated = 'foo' JSON::Validator.merge_missing_values(updated, original) assert_equal('foo', original) end def test_merge_missing_values_for_empty_array original = [] updated = [] JSON::Validator.merge_missing_values(updated, original) assert_equal([], original) end def test_merge_missing_values_for_empty_hash original = {} updated = {} JSON::Validator.merge_missing_values(updated, original) assert_equal({}, original) end def test_merge_missing_values_for_new_values original = {:hello => 'world'} updated = {'hello' => 'world', 'foo' => 'bar'} JSON::Validator.merge_missing_values(updated, original) assert_equal({:hello => 'world', 'foo' => 'bar'}, original) end def test_merge_missing_values_for_nested_array original = [:hello, 'world', 1, 2, 3, {:foo => :bar, 'baz' => 'qux'}] updated = ['hello', 'world', 1, 2, 3, {'foo' => 'bar', 'baz' => 'qux', 'this_is' => 'new'}] JSON::Validator.merge_missing_values(updated, original) assert_equal([:hello, 'world', 1, 2, 3, {:foo => :bar, 'baz' => 'qux', 'this_is' => 'new'}], original) end def test_merge_missing_values_for_nested_hash original = {:hello => 'world', :foo => ['bar', :baz, {:uno => {:due => 3}}]} updated = {'hello' => 'world', 'foo' => ['bar', 'baz', {'uno' => {'due' => 3, 'this_is' => 'new'}}], 'ack' => 'sed'} JSON::Validator.merge_missing_values(updated, original) assert_equal({:hello => 'world', :foo => ['bar', :baz, {:uno => {:due => 3, 'this_is' => 'new'}}], 'ack' => 'sed'}, original) end end ruby-json-schema-2.8.1/test/min_items_test.rb000066400000000000000000000006241341167564500212550ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class MinItemsTest < Minitest::Test def test_minitems_nils schema = { "type" => "array", "minItems" => 1, "items" => { "type" => "object" } } errors = JSON::Validator.fully_validate(schema, [nil]) assert_equal(errors.length, 1) assert(errors[0] !~ /minimum/) assert(errors[0] =~ /null/) end end ruby-json-schema-2.8.1/test/one_of_test.rb000066400000000000000000000054231341167564500205400ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class OneOfTest < Minitest::Test def test_one_of_links_schema schema = schema_fixture_path('one_of_ref_links_schema.json') data = data_fixture_path('one_of_ref_links_data.json') assert_valid schema, data end def test_one_of_with_string_patterns schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "oneOf" => [ { "properties" => {"a" => {"type" => "string", "pattern" => "foo"}}, }, { "properties" => {"a" => {"type" => "string", "pattern" => "bar"}}, }, { "properties" => {"a" => {"type" => "string", "pattern" => "baz"}}, } ] } assert_valid schema, { "a" => "foo" } refute_valid schema, { "a" => "foobar" } assert_valid schema, { "a" => "baz" } refute_valid schema, { "a" => 5 } end def test_one_of_sub_errors schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "oneOf" => [ { "properties" => {"a" => {"type" => "string", "pattern" => "foo"}}, }, { "properties" => {"a" => {"type" => "string", "pattern" => "bar"}}, }, { "properties" => {"a" => {"type" => "number", "minimum" => 10}}, } ] } errors = JSON::Validator.fully_validate(schema, { "a" => 5 }, :errors_as_objects => true) nested_errors = errors[0][:errors] assert_equal([:oneof_0,:oneof_1,:oneof_2], nested_errors.keys, 'should have nested errors for each allOf subschema') assert_match(/the property '#\/a' of type Integer did not match the following type: string/i, nested_errors[:oneof_0][0][:message]) assert_match(/the property '#\/a' did not have a minimum value of 10, inclusively/i, nested_errors[:oneof_2][0][:message]) end def test_one_of_sub_errors_message schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "oneOf" => [ { "properties" => {"a" => {"type" => "string", "pattern" => "foo"}}, }, { "properties" => {"a" => {"type" => "string", "pattern" => "bar"}}, }, { "properties" => {"a" => {"type" => "number", "minimum" => 10}}, } ] } errors = JSON::Validator.fully_validate(schema, { "a" => 5 }) expected_message = """The property '#/' of type object did not match any of the required schemas. The schema specific errors were: - oneOf #0: - The property '#/a' of type integer did not match the following type: string - oneOf #1: - The property '#/a' of type integer did not match the following type: string - oneOf #2: - The property '#/a' did not have a minimum value of 10, inclusively""" assert_equal(expected_message, errors[0]) end end ruby-json-schema-2.8.1/test/relative_definition_test.rb000066400000000000000000000010651341167564500233140ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class RelativeDefinitionTest < Minitest::Test 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} refute_valid schema, {"a" => "foo"} end end ruby-json-schema-2.8.1/test/ruby_schema_test.rb000066400000000000000000000024101341167564500215650ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class RubySchemaTest < Minitest::Test def test_string_keys schema = { "type" => 'object', "required" => ["a"], "properties" => { "a" => {"type" => "integer", "default" => 42}, "b" => {"type" => "integer"} } } assert_valid schema, { "a" => 5 } end def test_symbol_keys schema = { :type => 'object', :required => ["a"], :properties => { :a => {:type => "integer", :default => 42}, :b => {:type => "integer"} } } assert_valid schema, { :a => 5 } end def test_symbol_keys_in_hash_within_array schema = { :type => 'object', :properties => { :a => { :type => "array", :items => [ { :properties => { :b => { :type => "integer" } } } ] } } } data = { :a => [ { :b => 1 } ] } 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 ruby-json-schema-2.8.1/test/schema_reader_test.rb000066400000000000000000000046501341167564500220560ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class SchemaReaderTest < Minitest::Test ADDRESS_SCHEMA_URI = 'http://json-schema.org/address' ADDRESS_SCHEMA_PATH = File.expand_path('../schemas/address_microformat.json', __FILE__) def stub_address_request(body = File.read(ADDRESS_SCHEMA_PATH)) stub_request(:get, ADDRESS_SCHEMA_URI). to_return(:body => body, :status => 200) end def test_accept_all_uris stub_address_request reader = JSON::Schema::Reader.new schema = reader.read(ADDRESS_SCHEMA_URI) assert_equal schema.uri, Addressable::URI.parse("#{ADDRESS_SCHEMA_URI}#") end def test_accept_all_files reader = JSON::Schema::Reader.new schema = reader.read(ADDRESS_SCHEMA_PATH) assert_equal schema.uri, Addressable::URI.convert_path(ADDRESS_SCHEMA_PATH + '#') end def test_refuse_all_uris reader = JSON::Schema::Reader.new(:accept_uri => false) refute reader.accept_uri?(Addressable::URI.parse('http://foo.com')) end def test_refuse_all_files reader = JSON::Schema::Reader.new(:accept_file => false) refute reader.accept_file?(Pathname.new('/foo/bar/baz')) end def test_accept_uri_proc reader = JSON::Schema::Reader.new( :accept_uri => proc { |uri| uri.host == 'json-schema.org' } ) assert reader.accept_uri?(Addressable::URI.parse('http://json-schema.org/address')) refute reader.accept_uri?(Addressable::URI.parse('http://sub.json-schema.org/address')) end def test_accept_file_proc test_root = Pathname.new(__FILE__).expand_path.dirname reader = JSON::Schema::Reader.new( :accept_file => proc { |path| path.to_s.start_with?(test_root.to_s) } ) assert reader.accept_file?(test_root.join('anything.json')) refute reader.accept_file?(test_root.join('..', 'anything.json')) end def test_file_scheme reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false) error = assert_raises(JSON::Schema::ReadRefused) do reader.read('file://' + ADDRESS_SCHEMA_PATH) end assert_equal(:file, error.type) assert_equal(ADDRESS_SCHEMA_PATH, error.location) assert_equal("Read of file at #{ADDRESS_SCHEMA_PATH} refused", error.message) end def test_parse_error stub_address_request('this is totally not valid JSON!') reader = JSON::Schema::Reader.new assert_raises(JSON::Schema::JsonParseError) do reader.read(ADDRESS_SCHEMA_URI) end end end ruby-json-schema-2.8.1/test/schema_validation_test.rb000066400000000000000000000110131341167564500227350ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) require 'tmpdir' class SchemaValidationTest < Minitest::Test def valid_schema_v3 { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "b" => { "required" => true } } } end def invalid_schema_v3 { "$schema" => "http://json-schema.org/draft-03/schema#", "type" => "object", "properties" => { "b" => { "required" => "true" } } } end def valid_schema_v4 { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["b"], "properties" => { } } end def invalid_schema_v4 { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => "b", "properties" => { } } end def symbolized_schema { :type => :object, :required => [ :id, :name, :real_name, :role, :website, :biography, :created_at, :demographic ], :properties => { :id => { :type => [ :integer ] }, :name => { :type => [ :string ] }, :real_name => { :type => [ :string ] }, :role => { :type => [ :string ] }, :website => { :type => [ :string, :null ] }, :created_at => { :type => [ :string ] }, :biography => { :type => [ :string, :null ] } }, :relationships => { :demographic => { :type => :object, :required => [ :id, :gender ], :properties => { :id => { :type => [ :integer ] }, :gender => { :type => [ :string ] } } } } } end def test_draft03_validation data = {"b" => {"a" => 5}} assert(JSON::Validator.validate(valid_schema_v3,data,:validate_schema => true, :version => :draft3)) assert(!JSON::Validator.validate(invalid_schema_v3,data,:validate_schema => true, :version => :draft3)) end def test_validate_just_schema_draft03 errors = JSON::Validator.fully_validate_schema(valid_schema_v3, :version => :draft3) assert_equal [], errors errors = JSON::Validator.fully_validate_schema(invalid_schema_v3, :version => :draft3) assert_equal 1, errors.size assert_match(/the property .*required.*did not match/i, errors.first) end def test_draft04_validation data = {"b" => {"a" => 5}} assert(JSON::Validator.validate(valid_schema_v4,data,:validate_schema => true, :version => :draft4)) assert(!JSON::Validator.validate(invalid_schema_v4,data,:validate_schema => true, :version => :draft4)) end def test_validate_just_schema_draft04 errors = JSON::Validator.fully_validate_schema(valid_schema_v4, :version => :draft4) assert_equal [], errors errors = JSON::Validator.fully_validate_schema(invalid_schema_v4, :version => :draft4) assert_equal 1, errors.size assert_match(/the property .*required.*did not match/i, errors.first) end def test_validate_schema_3_without_version_option data = {"b" => {"a" => 5}} assert(JSON::Validator.validate(valid_schema_v3,data,:validate_schema => true)) assert(!JSON::Validator.validate(invalid_schema_v3,data,:validate_schema => true)) end def test_schema_validation_from_different_directory Dir.mktmpdir do |tmpdir| Dir.chdir(tmpdir) do data = {"b" => {"a" => 5}} assert(JSON::Validator.validate(valid_schema_v4,data,:validate_schema => true, :version => :draft4)) assert(!JSON::Validator.validate(invalid_schema_v4,data,:validate_schema => true, :version => :draft4)) end end end def test_validate_schema_with_symbol_keys data = { "created_at" => "2014-01-25T00:58:33-08:00", "id" => 8517194300913402149003, "name" => "chelsey", "real_name" => "Mekhi Hegmann", "website" => nil, "role" => "user", "biography" => nil, "demographic" => nil } assert(JSON::Validator.validate!(symbolized_schema, data, :validate_schema => true)) end end ruby-json-schema-2.8.1/test/schemas/000077500000000000000000000000001341167564500173265ustar00rootroot00000000000000ruby-json-schema-2.8.1/test/schemas/address_microformat.json000066400000000000000000000012001341167564500242410ustar00rootroot00000000000000{ "description": "An Address following the convention of http://microformats.org/wiki/hcard", "type": "object", "properties": { "post-office-box": { "type": "string" }, "extended-address": { "type": "string" }, "street-address": { "type": "string" }, "locality":{ "type": "string" }, "region": { "type": "string" }, "postal-code": { "type": "string" }, "country-name": { "type": "string"} }, "required": ["locality", "region", "country-name"], "dependencies": { "post-office-box": "street-address", "extended-address": "street-address" } } ruby-json-schema-2.8.1/test/schemas/all_of_ref_base_schema.json000066400000000000000000000001211341167564500246150ustar00rootroot00000000000000{ "type": "object", "properties" : { "name" : { "type": "integer" } } } ruby-json-schema-2.8.1/test/schemas/all_of_ref_schema.json000066400000000000000000000002201341167564500236230ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#", "type" : "object", "allOf" : [ { "$ref" : "all_of_ref_base_schema.json" } ] } ruby-json-schema-2.8.1/test/schemas/any_of_ref_jane_schema.json000066400000000000000000000001431341167564500246430ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "jane" } ruby-json-schema-2.8.1/test/schemas/any_of_ref_jimmy_schema.json000066400000000000000000000001441341167564500250540ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "jimmy" } ruby-json-schema-2.8.1/test/schemas/any_of_ref_john_schema.json000066400000000000000000000001431341167564500246640ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "john" } ruby-json-schema-2.8.1/test/schemas/any_of_ref_schema.json000066400000000000000000000005421341167564500236510ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "object" , "properties" : { "names" : { "type" : "array" , "items" : { "anyOf" : [ { "$ref" : "any_of_ref_john_schema.json" } , { "$ref" : "any_of_ref_jane_schema.json" } , { "$ref" : "any_of_ref_jimmy_schema.json" } ] } } } } ruby-json-schema-2.8.1/test/schemas/definition_schema.json000066400000000000000000000004071341167564500236720ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "description": "schema with definition", "type": "object", "properties": { "a": { "$ref": "#/definitions/foo" } }, "definitions": { "foo": { "type": "integer" } } } ruby-json-schema-2.8.1/test/schemas/definition_schema_with_special_characters.json000066400000000000000000000003441341167564500306240ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "a": { "$ref": "#/definitions/foo:bar" } }, "definitions": { "foo:bar": { "type": "integer" } } } ruby-json-schema-2.8.1/test/schemas/extends_and_additionalProperties_false_schema.json000066400000000000000000000011001341167564500314440ustar00rootroot00000000000000{ "type": "object", "extends": {"$ref":"inner_schema.json#"}, "properties": { "outerA": { "description": "blah", "additionalProperties": false, "properties": { "outerA1": { "type":"boolean" } } }, "outerB": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "extends": {"$ref":"inner_schema.json#"}, "additionalProperties": false } }, "outerC": { "description": "blah", "type":"boolean" } }, "additionalProperties": false } ruby-json-schema-2.8.1/test/schemas/extends_and_patternProperties_schema.json000066400000000000000000000010461341167564500276500ustar00rootroot00000000000000{ "type": "object", "extends": {"$ref":"inner_schema.json#"}, "patternProperties": { "outerA": { "description": "blah", "additionalProperties": false, "properties": { "outerA1": { "type":"boolean" } } }, "outerB": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "extends": {"$ref":"inner_schema.json#"}, "additionalProperties": false } }, "outerC": { "description": "blah", "type":"boolean" } } } ruby-json-schema-2.8.1/test/schemas/good_schema_1.json000066400000000000000000000001601341167564500227060ustar00rootroot00000000000000{ "type" : "object", "properties" : { "a" : { "type" : "integer" } }, "required": ["a"] } ruby-json-schema-2.8.1/test/schemas/good_schema_2.json000066400000000000000000000001731341167564500227130ustar00rootroot00000000000000{ "type" : "object", "properties" : { "b" : { "$ref" : "good_schema_1.json" } }, "required": ["b"] } ruby-json-schema-2.8.1/test/schemas/good_schema_extends1.json000066400000000000000000000001571341167564500243070ustar00rootroot00000000000000{ "type" : "object", "extends": {"$ref": "good_schema_1.json"}, "properties" : { "c" : { } } } ruby-json-schema-2.8.1/test/schemas/good_schema_extends2.json000066400000000000000000000002351341167564500243050ustar00rootroot00000000000000{ "type" : "object", "extends": [ {"$ref": "good_schema_1.json"}, {"$ref": "good_schema_2.json"} ], "properties" : { "c" : { } } } ruby-json-schema-2.8.1/test/schemas/inner_schema.json000066400000000000000000000004171341167564500226560ustar00rootroot00000000000000{ "type": "object", "properties": { "innerA": { "description": "blah", "type":"boolean" }, "innerB": { "description": "blah", "type":"boolean" }, "innerC": { "description": "blah", "type": "boolean" } } } ruby-json-schema-2.8.1/test/schemas/one_of_ref_links_schema.json000066400000000000000000000004651341167564500250470ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties": { "links" : { "type" : "array" , "items" : { "type" : "object" , "oneOf" : [ { "$ref" : "self_link_schema.json"} , { "$ref" : "up_link_schema.json" } ] } } } } ruby-json-schema-2.8.1/test/schemas/ref john with spaces schema.json000066400000000000000000000003061341167564500253270ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#", "type" : "object", "required" : ["first"], "properties": { "first": { "type": "string", "enum": ["john"] } } } ruby-json-schema-2.8.1/test/schemas/relative_definition_schema.json000066400000000000000000000002321341167564500255610ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "a": { "$ref": "definition_schema.json#/definitions/foo" } } }ruby-json-schema-2.8.1/test/schemas/self_link_schema.json000066400000000000000000000004211341167564500235040ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties" : { "rel" : { "type" : "array" , "items" : [ { "type" : "string" , "pattern" : "self" } ] } , "href" : { "type" : "string" } } } ruby-json-schema-2.8.1/test/schemas/up_link_schema.json000066400000000000000000000004171341167564500232040ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties" : { "rel" : { "type" : "array" , "items" : [ { "type" : "string" , "pattern" : "up" } ] } , "href" : { "type" : "string" } } } ruby-json-schema-2.8.1/test/stringify_test.rb000066400000000000000000000024071341167564500213100ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class StringifyTest < Minitest::Test def test_stringify_on_hash hash = { :a => 'foo', 'b' => :bar } assert_equal({'a' => 'foo', 'b' => 'bar'}, JSON::Schema.stringify(hash), 'symbol keys should be converted to strings') end def test_stringify_on_array array = [ :a, 'b' ] assert_equal(['a', 'b'], JSON::Schema.stringify(array), 'symbols in an array should be converted to strings') end def test_stringify_on_hash_of_arrays hash = { :a => [:foo], 'b' => :bar } assert_equal({'a' => ['foo'], 'b' => 'bar'}, JSON::Schema.stringify(hash), 'symbols in a nested array should be converted to strings') end def test_stringify_on_array_of_hashes array = [ :a, { :b => :bar } ] assert_equal(['a', {'b' => 'bar'}], JSON::Schema.stringify(array), 'symbols keys in a nested hash should be converted to strings') end def test_stringify_on_hash_of_hashes hash = { :a => { :b => { :foo => :bar } } } assert_equal({'a' => {'b' => {'foo' => 'bar'} } }, JSON::Schema.stringify(hash), 'symbols in a nested hash of hashes should be converted to strings') end end ruby-json-schema-2.8.1/test/support/000077500000000000000000000000001341167564500174175ustar00rootroot00000000000000ruby-json-schema-2.8.1/test/support/array_validation.rb000066400000000000000000000051641341167564500233020ustar00rootroot00000000000000module ArrayValidation module ItemsTests def test_items_single_schema schema = { 'items' => { 'type' => 'string' } } assert_valid schema, [] assert_valid schema, ['a'] assert_valid schema, ['a', 'b'] refute_valid schema, [1] refute_valid schema, ['a', 1] # other types are disregarded assert_valid schema, {'a' => 'foo'} end def test_items_multiple_schemas schema = { 'items' => [ { 'type' => 'string' }, { 'type' => 'integer' } ] } assert_valid schema, ['b', 1] assert_valid schema, ['b', 1, nil] refute_valid schema, [1, 'b'] assert_valid schema, [] assert_valid schema, ['b'] assert_valid schema, ['b', 1, 25] end def test_minitems schema = { 'minItems' => 1 } assert_valid schema, [1] assert_valid schema, [1, 2] refute_valid schema, [] # other types are disregarded assert_valid schema, 5 end def test_maxitems schema = { 'maxItems' => 1 } assert_valid schema, [] assert_valid schema, [1] refute_valid schema, [1, 2] # other types are disregarded assert_valid schema, 5 end end module AdditionalItemsTests def test_additional_items_false schema = { 'items' => [ { 'type' => 'integer' }, { 'type' => 'string' } ], 'additionalItems' => false } assert_valid schema, [1, 'string'] assert_valid schema, [1] assert_valid schema, [] refute_valid schema, [1, 'string', 2] refute_valid schema, ['string', 1] end def test_additional_items_schema schema = { 'items' => [ { 'type' => 'integer' }, { 'type' => 'string' } ], 'additionalItems' => { 'type' => 'integer' } } assert_valid schema, [1, 'string'] assert_valid schema, [1, 'string', 2] refute_valid schema, [1, 'string', 'string'] end end module UniqueItemsTests def test_unique_items schema = { 'uniqueItems' => true } assert_valid schema, [nil, 5] refute_valid schema, [nil, nil] assert_valid schema, [true, false] refute_valid schema, [true, true] assert_valid schema, [4, 4.1] refute_valid schema, [4, 4] assert_valid schema, ['a', 'ab'] refute_valid schema, ['a', 'a'] assert_valid schema, [[1], [2]] refute_valid schema, [[1], [1]] assert_valid schema, [{'b' => 1}, {'c' => 2}] assert_valid schema, [{'b' => 1}, {'c' => 1}] refute_valid schema, [{'b' => 1}, {'b' => 1}] end end end ruby-json-schema-2.8.1/test/support/enum_validation.rb000066400000000000000000000047521341167564500231320ustar00rootroot00000000000000module EnumValidation module V1_V2 def test_enum_optional schema = { "properties" => { "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}], "optional" => true} } } data = {} assert_valid schema, data end end module V3_V4 def test_enum_optional schema = { "properties" => { "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}]} } } data = {} assert_valid schema, data end end module General def test_enum_general schema = { "properties" => { "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}]} } } data = { "a" => 1 } assert_valid schema, data data["a"] = 'boo' assert_valid schema, data data["a"] = [1,2,3] assert_valid schema, data data["a"] = {"a" => "b"} assert_valid schema, data data["a"] = 'taco' refute_valid schema, data end def test_enum_number_integer_includes_float schema = { "properties" => { "a" => { "type" => "number", "enum" => [0, 1, 2] } } } data = { "a" => 0 } assert_valid schema, data data["a"] = 0.0 assert_valid schema, data data["a"] = 1 assert_valid schema, data data["a"] = 1.0 assert_valid schema, data end def test_enum_number_float_includes_integer schema = { "properties" => { "a" => { "type" => "number", "enum" => [0.0, 1.0, 2.0] } } } data = { "a" => 0.0 } assert_valid schema, data data["a"] = 0 assert_valid schema, data data["a"] = 1.0 assert_valid schema, data data["a"] = 1 assert_valid schema, data end def test_enum_integer_excludes_float schema = { "properties" => { "a" => { "type" => "integer", "enum" => [0, 1, 2] } } } data = { "a" => 0 } assert_valid schema, data data["a"] = 0.0 refute_valid schema, data data["a"] = 1 assert_valid schema, data data["a"] = 1.0 refute_valid schema, data end def test_enum_with_schema_validation schema = { "properties" => { "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}]} } } data = { "a" => 1 } assert_valid(schema, data, :validate_schema => true) end end end ruby-json-schema-2.8.1/test/support/number_validation.rb000066400000000000000000000034331341167564500234510ustar00rootroot00000000000000module NumberValidation module MinMaxTests def test_minimum schema = { 'properties' => { 'a' => { 'minimum' => 5 } } } assert_valid schema, {'a' => 5} assert_valid schema, {'a' => 6} refute_valid schema, {'a' => 4} refute_valid schema, {'a' => 4.99999} # other types are disregarded assert_valid schema, {'a' => 'str'} end def test_exclusive_minimum schema = { 'properties' => { 'a' => { 'minimum' => 5 }.merge(exclusive_minimum) } } assert_valid schema, {'a' => 6} assert_valid schema, {'a' => 5.0001} refute_valid schema, {'a' => 5} end def test_maximum schema = { 'properties' => { 'a' => { 'maximum' => 5 } } } assert_valid schema, {'a' => 4} assert_valid schema, {'a' => 5} refute_valid schema, {'a' => 6} refute_valid schema, {'a' => 5.0001} end def test_exclusive_maximum schema = { 'properties' => { 'a' => { 'maximum' => 5 }.merge(exclusive_maximum) } } assert_valid schema, {'a' => 4} assert_valid schema, {'a' => 4.99999} refute_valid schema, {'a' => 5} end end # draft3 introduced `divisibleBy`, renamed to `multipleOf` in draft4. # Favor the newer name, but the behavior should be identical. module MultipleOfTests def multiple_of 'multipleOf' end def test_multiple_of schema = { 'properties' => { 'a' => { multiple_of => 1.1 } } } assert_valid schema, {'a' => 0} assert_valid schema, {'a' => 2.2} refute_valid schema, {'a' => 3.4} # other types are disregarded assert_valid schema, {'a' => 'hi'} end end end ruby-json-schema-2.8.1/test/support/object_validation.rb000066400000000000000000000034561341167564500234340ustar00rootroot00000000000000module ObjectValidation module AdditionalPropertiesTests def test_additional_properties_false schema = { 'properties' => { 'a' => { 'type' => 'integer' } }, 'additionalProperties' => false } assert_valid schema, {'a' => 1} refute_valid schema, {'a' => 1, 'b' => 2} end def test_additional_properties_schema schema = { 'properties' => { 'a' => { 'type' => 'integer' } }, 'additionalProperties' => { 'type' => 'string' } } assert_valid schema, {'a' => 1} assert_valid schema, {'a' => 1, 'b' => 'hi'} refute_valid schema, {'a' => 1, 'b' => 2} end end module PatternPropertiesTests def test_pattern_properties schema = { 'patternProperties' => { "\\d+ taco" => { 'type' => 'integer' } } } assert_valid schema, {'1 taco' => 1, '20 taco' => 20} assert_valid schema, {'foo' => true, '1 taco' => 1} refute_valid schema, {'1 taco' => 'yum'} end def test_pattern_properties_additional_properties_false schema = { 'patternProperties' => { "\\d+ taco" => { 'type' => 'integer' } }, 'additionalProperties' => false } assert_valid schema, {'1 taco' => 1} refute_valid schema, {'1 taco' => 'yum'} refute_valid schema, {'1 taco' => 1, 'foo' => true} end def test_pattern_properties_additional_properties_schema schema = { 'patternProperties' => { "\\d+ taco" => { 'type' => 'integer' } }, 'additionalProperties' => { 'type' => 'string' } } assert_valid schema, {'1 taco' => 1} assert_valid schema, {'1 taco' => 1, 'foo' => 'bar'} refute_valid schema, {'1 taco' => 1, 'foo' => 2} end end end ruby-json-schema-2.8.1/test/support/strict_validation.rb000066400000000000000000000053651341167564500234770ustar00rootroot00000000000000module StrictValidation def test_strict_properties schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} } } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) end def test_strict_error_message schema = { :type => 'object', :properties => { :a => { :type => 'string' } } } data = { :a => 'abc', :b => 'abc' } errors = JSON::Validator.fully_validate(schema,data,:strict => true) assert_match("The property '#/' contained undefined properties: 'b' in schema", errors[0]) end def test_strict_properties_additional_props schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} }, "additionalProperties" => {"type" => "integer"} } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => 3} assert(JSON::Validator.validate(schema,data,:strict => true)) end def test_strict_properties_pattern_props schema = { "properties" => { "a" => {"type" => "string"}, "b" => {"type" => "string"} }, "patternProperties" => {"\\d+ taco" => {"type" => "integer"}} } data = {"a" => "a"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"b" => "b"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b"} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => "c"} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "c" => 3} assert(!JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "23 taco" => 3} assert(JSON::Validator.validate(schema,data,:strict => true)) data = {"a" => "a", "b" => "b", "23 taco" => "cheese"} assert(!JSON::Validator.validate(schema,data,:strict => true)) end end ruby-json-schema-2.8.1/test/support/string_validation.rb000066400000000000000000000100251341167564500234620ustar00rootroot00000000000000module StringValidation module ValueTests def test_minlength schema = { 'properties' => { 'a' => { 'minLength' => 1 } } } assert_valid schema, {'a' => 't'} refute_valid schema, {'a' => ''} # other types are disregarded assert_valid schema, {'a' => 5} end def test_maxlength schema = { 'properties' => { 'a' => { 'maxLength' => 2 } } } assert_valid schema, {'a' => 'tt'} assert_valid schema, {'a' => ''} refute_valid schema, {'a' => 'ttt'} # other types are disregarded assert_valid schema, {'a' => 5} end def test_pattern schema = { 'properties' => { 'a' => { 'pattern' => "\\d+ taco" } } } assert_valid schema, {'a' => '156 taco bell'} refute_valid schema, {'a' => 'x taco'} # other types are disregarded assert_valid schema, {'a' => 5} end end module FormatTests # Draft1..3 use the format name `ip-address`; draft4 changed it to `ipv4`. def ipv4_format 'ip-address' end def test_format_unknown schema = { 'properties' => { 'a' => { 'format' => 'unknown' } } } assert_valid schema, {'a' => 'absolutely anything!'} assert_valid schema, {'a' => ''} end def test_format_union schema = { 'properties' => { 'a' => { 'type' => ['string', 'null'], 'format' => 'date-time' } } } assert_valid schema, {'a' => nil} refute_valid schema, {'a' => 'wrong'} end def test_format_ipv4 schema = { 'properties' => { 'a' => { 'format' => ipv4_format } } } assert_valid schema, {"a" => "1.1.1.1"} refute_valid schema, {"a" => "1.1.1"} refute_valid schema, {"a" => "1.1.1.300"} refute_valid schema, {"a" => "1.1.1"} refute_valid schema, {"a" => "1.1.1.1b"} # other types are disregarded assert_valid schema, {'a' => 5} end def test_format_ipv6 schema = { 'properties' => { 'a' => { 'format' => 'ipv6' } } } assert_valid schema, {"a" => "1111:2222:8888:9999:aaaa:cccc:eeee:ffff"} assert_valid schema, {"a" => "1111:0:8888:0:0:0:eeee:ffff"} assert_valid schema, {"a" => "1111:2222:8888::eeee:ffff"} assert_valid schema, {"a" => "::1"} refute_valid schema, {"a" => "1111:2222:8888:99999:aaaa:cccc:eeee:ffff"} refute_valid schema, {"a" => "1111:2222:8888:9999:aaaa:cccc:eeee:gggg"} refute_valid schema, {"a" => "1111:2222::9999::cccc:eeee:ffff"} refute_valid schema, {"a" => "1111:2222:8888:9999:aaaa:cccc:eeee:ffff:bbbb"} refute_valid schema, {"a" => "42"} refute_valid schema, {"a" => "b"} end end # Draft1..3 explicitly support `date`, `time` formats in addition to # the `date-time` format. module DateAndTimeFormatTests def test_format_time schema = { 'properties' => { 'a' => { 'format' => 'time' } } } assert_valid schema, {"a" => "12:00:00"} refute_valid schema, {"a" => "12:00"} refute_valid schema, {"a" => "12:00:60"} refute_valid schema, {"a" => "12:60:00"} refute_valid schema, {"a" => "24:00:00"} refute_valid schema, {"a" => "0:00:00"} refute_valid schema, {"a" => "-12:00:00"} refute_valid schema, {"a" => "12:00:00b"} assert_valid schema, {"a" => "12:00:00"} refute_valid schema, {"a" => "12:00:00\nabc"} end def test_format_date schema = { 'properties' => { 'a' => { 'format' => 'date' } } } assert_valid schema, {"a" => "2010-01-01"} refute_valid schema, {"a" => "2010-01-32"} refute_valid schema, {"a" => "n2010-01-01"} refute_valid schema, {"a" => "2010-1-01"} refute_valid schema, {"a" => "2010-01-1"} refute_valid schema, {"a" => "2010-01-01n"} refute_valid schema, {"a" => "2010-01-01\nabc"} end end end ruby-json-schema-2.8.1/test/support/test_helper.rb000066400000000000000000000025411341167564500222640ustar00rootroot00000000000000if ENV['COVERAGE'] require 'simplecov' SimpleCov.start do add_filter '/test/' end end require 'minitest/autorun' require 'webmock/minitest' $LOAD_PATH.unshift(File.expand_path('../../../lib', __FILE__)) require 'json-schema' Dir[File.join(File.expand_path('../', __FILE__), '*.rb')].each do |support_file| require support_file unless support_file == __FILE__ end class Minitest::Test def suppress_warnings old_verbose = $VERBOSE $VERBOSE = nil begin yield ensure $VERBOSE = old_verbose end end def schema_fixture_path(filename) File.join(File.dirname(__FILE__), '../schemas', filename) end def data_fixture_path(filename) File.join(File.dirname(__FILE__), '../data', filename) end def assert_valid(schema, data, options = {}, msg = "#{data.inspect} should be valid for schema:\n#{schema.inspect}") errors = validation_errors(schema, data, options) assert_equal([], errors, msg) end def refute_valid(schema, data, options = {}, msg = "#{data.inspect} should be invalid for schema:\n#{schema.inspect}") errors = validation_errors(schema, data, options) refute_equal([], errors, msg) end def validation_errors(schema, data, options) options = { :clear_cache => true, :validate_schema => true }.merge(options) JSON::Validator.fully_validate(schema, data, options) end end ruby-json-schema-2.8.1/test/support/test_suite_ignored_tests.yml000066400000000000000000000133371341167564500252720ustar00rootroot00000000000000# These are test files which we know fail spectacularly, either because we # don't support that functionality or because they require external # dependencies. To allow finer-grained control over which tests to run, # you can replace `:all` with an array containing the names of individual # tests to skip. draft3: ref: - ref overrides any sibling keywords/remote ref valid, maxItems ignored optional: jsregex: :all format: - validation of regular expressions/a regular expression with unclosed parens is invalid - validation of e-mail addresses/an invalid e-mail address - validation of URIs/an invalid URI - validation of URIs/an invalid protocol-relative URI Reference - validation of URIs/an invalid URI though valid URI reference - validation of host names/a host name with a component too long - validation of host names/a host name containing illegal characters - validation of host names/a host name starting with an illegal character - validation of CSS colors/an invalid CSS color code - validation of CSS colors/an invalid CSS color name - validation of CSS colors/a CSS color name containing invalid characters draft4: ref: - ref overrides any sibling keywords/remote ref valid, maxItems ignored - ref overrides any sibling keywords/ref valid, maxItems ignored optional: format: - validation of URIs/an invalid URI - validation of URIs/an invalid protocol-relative URI Reference - validation of URIs/an invalid URI though valid URI reference - validation of e-mail addresses/an invalid e-mail address - validation of host names/a host name with a component too long - validation of host names/a host name containing illegal characters - validation of host names/a host name starting with an illegal character ecmascript-regex: - ECMA 262 regex non-compliance/ECMA 262 has no support for \Z anchor from .NET bignum: - float comparison with high precision on negative numbers/comparison works for very negative numbers - float comparison with high precision/comparison works for high numbers draft6: allOf: - allOf with boolean schemas, some false/any value is invalid - allOf with boolean schemas, all false/any value is invalid - allOf with boolean schemas, all true/any value is valid anyOf: - anyOf with boolean schemas, all false/any value is invalid - anyOf with boolean schemas, all true/any value is valid - anyOf with boolean schemas, some true/any value is valid boolean_schema: :all const: :all contains: :all dependencies: - dependencies with boolean subschemas/empty object is valid - dependencies with boolean subschemas/object with both properties is invalid - dependencies with boolean subschemas/object with property having schema false is invalid - dependencies with boolean subschemas/object with property having schema true is valid - dependencies with empty array/empty object - dependencies with empty array/object with one property exclusiveMaximum: :all exclusiveMinimum: :all items: - items with boolean schema (false)/any non-empty array is invalid - items with boolean schema (false)/empty array is valid - items with boolean schema (true)/any array is valid - items with boolean schema (true)/empty array is valid - items with boolean schemas/array with one item is valid - items with boolean schemas/array with two items is invalid - items with boolean schemas/empty array is valid not: :all oneOf: - oneOf with boolean schemas, all false/any value is invalid - oneOf with boolean schemas, all true/any value is invalid - oneOf with boolean schemas, one true/any value is valid - oneOf with boolean schemas, more than one true/any value is invalid patternProperties: - patternProperties with boolean schemas/object with property matching schema false is invalid - patternProperties with boolean schemas/object with both properties is invalid - patternProperties with boolean schemas/object with property matching schema true is valid - patternProperties with boolean schemas/empty object is valid properties: - properties with boolean schema/only 'true' property present is valid - properties with boolean schema/only 'false' property present is invalid - properties with boolean schema/no property present is valid - properties with boolean schema/both properties present is invalid propertyNames: :all ref: - ref overrides any sibling keywords/remote ref valid, maxItems ignored - ref overrides any sibling keywords/ref valid, maxItems ignored - $ref to boolean schema true/any value is valid - $ref to boolean schema false/any value is invalid required: - required with empty array/property not required optional: bignum: - float comparison with high precision/comparison works for high numbers - float comparison with high precision on negative numbers/comparison works for very negative numbers format: - validation of URIs/an invalid URI - validation of URIs/an invalid protocol-relative URI Reference - validation of URIs/an invalid URI though valid URI reference - validation of e-mail addresses/an invalid e-mail address - validation of host names/a host name with a component too long - validation of host names/a host name containing illegal characters - validation of host names/a host name starting with an illegal character ecmascript-regex: - ECMA 262 regex non-compliance/ECMA 262 has no support for \Z anchor from .NET zeroTerminatedFloats: - some languages do not distinguish between different types of numeric value/a float is not an integer even without fractional part ruby-json-schema-2.8.1/test/support/type_validation.rb000066400000000000000000000040261341167564500231410ustar00rootroot00000000000000module TypeValidation # The draft4 schema refers to the JSON types as 'simple types'; # see draft4#/definitions/simpleTypes module SimpleTypeTests TYPES = { 'integer' => 5, 'number' => 5.0, 'string' => 'str', 'boolean' => true, 'object' => {}, 'array' => [], 'null' => nil } TYPES.each do |name, value| other_values = TYPES.values.reject { |v| v == value } define_method(:"test_#{name}_type_property") do schema = { 'properties' => { 'a' => { 'type' => name } } } assert_valid schema, {'a' => value} other_values.each do |other_value| refute_valid schema, {'a' => other_value} end end define_method(:"test_#{name}_type_value") do schema = { 'type' => name } assert_valid schema, value other_values.each do |other_value| schema = { 'type' => name } refute_valid schema, other_value end end end def test_type_union schema = { 'type' => ['integer', 'string'] } assert_valid schema, 5 assert_valid schema, 'str' refute_valid schema, nil refute_valid schema, [5, 'str'] end end # The draft1..3 schemas support an additional type, `any`. module AnyTypeTests def test_any_type schema = { 'type' => 'any' } SimpleTypeTests::TYPES.values.each do |value| assert_valid schema, value end end end # The draft1..3 schemas support schemas as values for `type`. module SchemaUnionTypeTests def test_union_type_with_schemas schema = { 'properties' => { 'a' => { 'type' => [ {'type' => 'string'}, {'type' => 'object', 'properties' => { 'b' => { 'type' => 'integer' }}} ] } } } assert_valid schema, {'a' => 'test'} refute_valid schema, {'a' => 5} assert_valid schema, {'a' => {'b' => 5}} refute_valid schema, {'a' => {'b' => 'taco'}} end end end ruby-json-schema-2.8.1/test/type_attribute_test.rb000066400000000000000000000011611341167564500223320ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) 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') assert_equal(type_of_data(1), 'integer') assert_equal(type_of_data(true), 'boolean') assert_equal(type_of_data(false), 'boolean') assert_equal(type_of_data(Hash.new), 'object') assert_equal(type_of_data(nil), 'null') assert_equal(type_of_data(Object.new), 'any') end private def type_of_data(data) JSON::Schema::TypeAttribute.type_of_data(data) end end ruby-json-schema-2.8.1/test/uri_parsing_test.rb000066400000000000000000000032411341167564500216110ustar00rootroot00000000000000# coding: utf-8 require File.expand_path('../support/test_helper', __FILE__) class UriParsingTest < Minitest::Test def test_asian_characters schema = { "$schema"=> "http://json-schema.org/draft-04/schema#", "id"=> "http://俺:鍵@例え.テスト/p?条件#ここ#", "type" => "object", "required" => ["a"], "properties" => { "a" => { "id" => "a", "type" => "integer" } } } data = { "a" => 5 } assert_valid schema, data end def test_schema_ref_with_empty_fragment schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["names"], "properties"=> { "names"=> { "type"=> "array", "items"=> { "anyOf"=> [ { "$ref" => "test/schemas/ref john with spaces schema.json#" }, ] } } } } data = {"names" => [{"first" => "john"}]} assert_valid schema, data end def test_schema_ref_from_file_with_spaces schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "object", "required" => ["names"], "properties"=> { "names"=> { "type"=> "array", "items"=> { "anyOf"=> [ { "$ref" => "test/schemas/ref john with spaces schema.json" } ] } } } } data = {"names" => [{"first" => "john"}]} assert_valid schema, data end def test_schema_from_file_with_spaces data = {"first" => "john"} schema = "test/schemas/ref john with spaces schema.json" assert_valid schema, data end end ruby-json-schema-2.8.1/test/uri_util_test.rb000066400000000000000000000170301341167564500211240ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class UriUtilTest < Minitest::Test def populate_cache_with(str, &blk) cached_uri = Addressable::URI.parse(str) Addressable::URI.stub(:parse, cached_uri, &blk) cached_uri end def teardown JSON::Util::URI.clear_cache end def test_normalized_uri str = "https://www.google.com/search" uri = Addressable::URI.new(scheme: 'https', host: 'www.google.com', path: 'search') assert_equal uri, JSON::Util::URI.normalized_uri(str, '/home') end def test_normalized_uri_with_empty_fragment str = "https://www.google.com/search#" uri = Addressable::URI.new(scheme: 'https', host: 'www.google.com', path: 'search', fragment: nil) assert_equal uri, JSON::Util::URI.normalized_uri(str, '/home') end def test_normalized_uri_with_fragment str = "https://www.google.com/search#foo" uri = Addressable::URI.new(scheme: 'https', host: 'www.google.com', path: 'search', fragment: 'foo') assert_equal uri, JSON::Util::URI.normalized_uri(str, '/home') end def test_normalized_uri_for_absolute_path str = "/foo/bar.json" uri = Addressable::URI.new(scheme: 'file', host: '', path: '/foo/bar.json') assert_equal uri, JSON::Util::URI.normalized_uri(str, '/home') end def test_normalized_uri_for_relative_path str = "foo/bar.json" uri = Addressable::URI.new(scheme: 'file', host: '', path: '/home/foo/bar.json') assert_equal uri, JSON::Util::URI.normalized_uri(str, '/home') end def test_normalized_uri_for_file_path_with_host str = "file://localhost/foo/bar.json" uri = Addressable::URI.new(scheme: 'file', host: 'localhost', path: '/foo/bar.json') assert_equal uri, JSON::Util::URI.normalized_uri(str, '/home') end def test_uri_parse str = "https://www.google.com/search" uri = Addressable::URI.new(scheme: 'https', host: 'www.google.com', path: 'search') assert_equal uri, JSON::Util::URI.parse(str) end def test_invalid_uri_parse uri = ":::::::" assert_raises(JSON::Schema::UriError) do JSON::Util::URI.parse(uri) end end def test_normalization_cache cached_uri = populate_cache_with('www.google.com') do JSON::Util::URI.normalized_uri('foo') end assert_equal(cached_uri, JSON::Util::URI.normalized_uri('foo')) JSON::Util::URI.clear_cache refute_equal(cached_uri, JSON::Util::URI.normalized_uri('foo')) end def test_parse_cache cached_uri = populate_cache_with('www.google.com') do JSON::Util::URI.parse('foo') end assert_equal(cached_uri, JSON::Util::URI.parse('foo')) JSON::Util::URI.clear_cache refute_equal(cached_uri, JSON::Util::URI.parse('foo')) end def test_validator_clear_cache_for_normalized_uri cached_uri = populate_cache_with('www.google.com') do JSON::Util::URI.normalized_uri('foo') end assert_equal(cached_uri, JSON::Util::URI.normalized_uri('foo')) validation_errors({"type" => "string"}, "foo", :clear_cache => true) refute_equal(cached_uri, JSON::Util::URI.normalized_uri('foo')) end def test_validator_clear_cache_for_parse cached_uri = populate_cache_with('www.google.com') do JSON::Util::URI.parse('foo') end assert_equal(cached_uri, JSON::Util::URI.parse('foo')) validation_errors({"type" => "string"}, "foo", :clear_cache => true) refute_equal(cached_uri, JSON::Util::URI.parse('foo')) end def test_ref_fragment_path uri = '#some-thing' base = 'http://www.example.com/foo/#bar' assert_equal Addressable::URI.parse('http://www.example.com/foo/#some-thing'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://www.example.com/foo/#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_file_path uri = '/some/thing' base = 'http://www.example.com/foo/#bar' assert_equal Addressable::URI.parse('http://www.example.com/some/thing#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://www.example.com/some/thing#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_uri uri = 'http://foo-bar.com' base = 'http://www.example.com/foo/#bar' assert_equal Addressable::URI.parse('http://foo-bar.com/#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://foo-bar.com/#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_uri_with_path uri = 'http://foo-bar.com/some/thing' base = 'http://www.example.com/foo/#bar' assert_equal Addressable::URI.parse('http://foo-bar.com/some/thing#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://foo-bar.com/some/thing#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_uri_with_fragment uri = 'http://foo-bar.com/some/thing#foo' base = 'http://www.example.com/hello/#world' assert_equal Addressable::URI.parse('http://foo-bar.com/some/thing#foo'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://foo-bar.com/some/thing#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_uri_with_fragment_and_base_with_no_fragment uri = 'http://foo-bar.com/some/thing#foo' base = 'http://www.example.com/hello' assert_equal Addressable::URI.parse('http://foo-bar.com/some/thing#foo'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://foo-bar.com/some/thing#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_relative_path uri = 'hello/world' base = 'http://www.example.com/foo/#bar' assert_equal Addressable::URI.parse('http://www.example.com/foo/hello/world#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://www.example.com/foo/hello/world#'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_addressable_uri_with_host uri = Addressable::URI.new(:host => 'foo-bar.com') base = 'http://www.example.com/hello/#world' assert_equal Addressable::URI.parse('http://www.example.com/foo-bar.com#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://www.example.com/hello/#world'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_addressable_uri_with_host_and_path uri = Addressable::URI.new(:host => 'foo-bar.com', :path => '/hello/world') base = 'http://www.example.com/a/#b' assert_equal Addressable::URI.parse('http://www.example.com/foo-bar.com/hello/world#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('http://www.example.com/hello/world'), JSON::Util::URI.absolutize_ref(uri, base) end def test_ref_addressable_uri_with_shceme_host_and_path uri = Addressable::URI.new(:scheme => 'https', :host => 'foo-bar.com', :path => '/hello/world') base = 'http://www.example.com/a/#b' assert_equal Addressable::URI.parse('https://foo-bar.com/hello/world#'), JSON::Util::URI.normalize_ref(uri, base) assert_equal Addressable::URI.parse('https://foo-bar.com/hello/world'), JSON::Util::URI.absolutize_ref(uri, base) end end ruby-json-schema-2.8.1/test/validator_schema_reader_test.rb000066400000000000000000000030331341167564500241150ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) class ValidatorSchemaReaderTest < Minitest::Test class MockReader < JSON::Schema::Reader def read(location) return super unless location.to_s == 'http://any.url/at/all' schema = { '$schema' => 'http://json-schema.org/draft-04/schema#', 'type' => 'string', 'minLength' => 2 } JSON::Schema.new(schema, Addressable::URI.parse(location.to_s)) end end def setup @original_reader = JSON::Validator.schema_reader end def teardown JSON::Validator.schema_reader = @original_reader end def test_default_schema_reader reader = JSON::Validator.schema_reader assert reader.accept_uri?(Addressable::URI.parse('http://example.com')) assert reader.accept_file?(Pathname.new('/etc/passwd')) end def test_set_default_schema_reader JSON::Validator.schema_reader = MockReader.new schema = { '$ref' => 'http://any.url/at/all' } assert_valid schema, 'abc' refute_valid schema, 'a' end def test_validate_with_reader reader = MockReader.new schema = { '$ref' => 'http://any.url/at/all' } assert_valid schema, 'abc', :schema_reader => reader refute_valid schema, 'a', :schema_reader => reader end def test_validate_list_with_reader reader = MockReader.new schema = { '$ref' => 'http://any.url/at/all' } assert_valid schema, ['abc', 'def'], :schema_reader => reader, :list => true refute_valid schema, ['abc', 'a'], :schema_reader => reader, :list => true end end