pax_global_header00006660000000000000000000000064130463211500014505gustar00rootroot0000000000000052 comment=20734c1bc388fdc16d53837b2ce9599f21cfa4b7 json-schema-2.8.0/000077500000000000000000000000001304632115000137235ustar00rootroot00000000000000json-schema-2.8.0/.gitignore000066400000000000000000000000671304632115000157160ustar00rootroot00000000000000/.project .*.swp pkg *.gem /Gemfile.lock .bundle .idea json-schema-2.8.0/.gitmodules000066400000000000000000000002121304632115000160730ustar00rootroot00000000000000[submodule "test/test-suite"] path = test/test-suite branch = master url = git://github.com/json-schema-org/JSON-Schema-Test-Suite.git json-schema-2.8.0/.travis.yml000066400000000000000000000007551304632115000160430ustar00rootroot00000000000000language: "ruby" rvm: - "2.0" - "2.1" - "2.2" - "2.3.3" - "2.4.0" - "jruby-9.1.7.0" 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.3.3" gemfile: "gemfiles/Gemfile.multi_json.x" - rvm: "2.3.3" gemfile: "gemfiles/Gemfile.yajl-ruby.x" - rvm: "2.3.3" gemfile: "gemfiles/Gemfile.uuidtools.x" json-schema-2.8.0/CHANGELOG.md000066400000000000000000000040401304632115000155320ustar00rootroot00000000000000# 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.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` json-schema-2.8.0/CONTRIBUTING.md000066400000000000000000000015761304632115000161650ustar00rootroot00000000000000The 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. json-schema-2.8.0/CONTRIBUTORS.md000066400000000000000000000015521304632115000162050ustar00rootroot00000000000000CONTRIBUTORS ------------ * 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 json-schema-2.8.0/Gemfile000066400000000000000000000001241304632115000152130ustar00rootroot00000000000000source "https://rubygems.org" gemspec gem "json", ">= 1.7", :platforms => :mri_19 json-schema-2.8.0/LICENSE.md000066400000000000000000000020651304632115000153320ustar00rootroot00000000000000Copyright (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.json-schema-2.8.0/README.md000066400000000000000000000326421304632115000152110ustar00rootroot00000000000000[![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"}) ``` 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. json-schema-2.8.0/Rakefile000066400000000000000000000011361304632115000153710ustar00rootroot00000000000000require '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 sh "git submodule update --remote --quiet" end Rake::TestTask.new do |t| t.libs << "." # disabled warnings because addressable 2.4 has lots of them t.warning = false t.verbose = true t.test_files = FileList.new('test/*_test.rb') end task :test => :update_common_tests task :default => :test json-schema-2.8.0/VERSION.yml000066400000000000000000000000331304632115000155670ustar00rootroot00000000000000major: 2 minor: 8 patch: 0 json-schema-2.8.0/gemfiles/000077500000000000000000000000001304632115000155165ustar00rootroot00000000000000json-schema-2.8.0/gemfiles/Gemfile.multi_json.x000066400000000000000000000001101304632115000214310ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "multi_json" json-schema-2.8.0/gemfiles/Gemfile.ruby_19.x000066400000000000000000000001471304632115000205520ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "json", "~> 1.0" gem "addressable", "< 2.5" json-schema-2.8.0/gemfiles/Gemfile.uuidtools.x000066400000000000000000000001071304632115000213030ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "uuidtools" json-schema-2.8.0/gemfiles/Gemfile.yajl-ruby.x000066400000000000000000000001071304632115000211720ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "yajl-ruby" json-schema-2.8.0/json-schema.gemspec000066400000000000000000000015761304632115000175100ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/000077500000000000000000000000001304632115000144715ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema.rb000066400000000000000000000015251304632115000172300ustar00rootroot00000000000000require '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/attributes/formats/*.rb")].each {|file| require file } Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*.rb")].sort!.each {|file| require file } json-schema-2.8.0/lib/json-schema/000077500000000000000000000000001304632115000167005ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/attribute.rb000066400000000000000000000027651304632115000212420ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/000077500000000000000000000000001304632115000210665ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/attributes/additionalitems.rb000066400000000000000000000020631304632115000245660ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/additionalproperties.rb000066400000000000000000000044511304632115000256440ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/allof.rb000066400000000000000000000031171304632115000225120ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/anyof.rb000066400000000000000000000034771304632115000225420ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/dependencies.rb000066400000000000000000000032311304632115000240400ustar00rootroot00000000000000require '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 class DependenciesV4Attribute < DependenciesAttribute def self.accept_value?(value) value.is_a?(Array) || value.is_a?(Hash) end end end end json-schema-2.8.0/lib/json-schema/attributes/disallow.rb000066400000000000000000000006061304632115000232330ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/divisibleby.rb000066400000000000000000000012711304632115000237210ustar00rootroot00000000000000require '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.new(data.to_s) % BigDecimal.new(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 json-schema-2.8.0/lib/json-schema/attributes/enum.rb000066400000000000000000000013661304632115000223650ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/extends.rb000066400000000000000000000032651304632115000230730ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/format.rb000066400000000000000000000010001304632115000226720ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/formats/000077500000000000000000000000001304632115000225415ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/attributes/formats/custom.rb000066400000000000000000000012471304632115000244040ustar00rootroot00000000000000require 'json-schema/attribute' 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 json-schema-2.8.0/lib/json-schema/attributes/formats/date.rb000066400000000000000000000015421304632115000240050ustar00rootroot00000000000000require 'json-schema/attribute' 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 json-schema-2.8.0/lib/json-schema/attributes/formats/date_time.rb000066400000000000000000000032761304632115000250310ustar00rootroot00000000000000require 'json-schema/attribute' 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 json-schema-2.8.0/lib/json-schema/attributes/formats/date_time_v4.rb000066400000000000000000000010411304632115000254260ustar00rootroot00000000000000require 'json-schema/attribute' 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 json-schema-2.8.0/lib/json-schema/attributes/formats/ip.rb000066400000000000000000000020211304632115000234710ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/formats/time.rb000066400000000000000000000020031304632115000240170ustar00rootroot00000000000000require 'json-schema/attribute' 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 json-schema-2.8.0/lib/json-schema/attributes/formats/uri.rb000066400000000000000000000011321304632115000236620ustar00rootroot00000000000000require 'json-schema/attribute' 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 json-schema-2.8.0/lib/json-schema/attributes/items.rb000066400000000000000000000015201304632115000225320ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/limit.rb000066400000000000000000000077041304632115000225410ustar00rootroot00000000000000require '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 class MinLengthAttribute < LimitAttribute def self.acceptable_type String end def self.limit_name 'minLength' end def self.error_message(schema) "was not of a minimum string length of #{limit(schema)}" end def self.value(data) data.length end end class MaxLengthAttribute < MinLengthAttribute def self.limit_name 'maxLength' end def self.error_message(schema) "was not of a maximum string length of #{limit(schema)}" end end class MinItemsAttribute < LimitAttribute def self.acceptable_type Array end def self.value(data) data.length end def self.limit_name 'minItems' end def self.error_message(schema) "did not contain a minimum number of items #{limit(schema)}" end end class MaxItemsAttribute < MinItemsAttribute def self.limit_name 'maxItems' end def self.error_message(schema) "had more items than the allowed #{limit(schema)}" end end class MinPropertiesAttribute < LimitAttribute def self.acceptable_type Hash end def self.value(data) data.size end def self.limit_name 'minProperties' end def self.error_message(schema) "did not contain a minimum number of properties #{limit(schema)}" end end class MaxPropertiesAttribute < MinPropertiesAttribute def self.limit_name 'maxProperties' end def self.error_message(schema) "had more properties than the allowed #{limit(schema)}" end end 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 class MaximumAttribute < NumericLimitAttribute def self.limit_name 'maximum' end def self.exclusive?(schema) schema['exclusiveMaximum'] end end class MaximumInclusiveAttribute < MaximumAttribute def self.exclusive?(schema) schema['maximumCanEqual'] == false end end class MinimumAttribute < NumericLimitAttribute def self.limit_name 'minimum' end def self.exclusive?(schema) schema['exclusiveMinimum'] end end class MinimumInclusiveAttribute < MinimumAttribute def self.exclusive?(schema) schema['minimumCanEqual'] == false end end end end json-schema-2.8.0/lib/json-schema/attributes/maxdecimal.rb000066400000000000000000000012231304632115000235150ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/multipleof.rb000066400000000000000000000003061304632115000235720ustar00rootroot00000000000000require 'json-schema/attributes/divisibleby' module JSON class Schema class MultipleOfAttribute < DivisibleByAttribute def self.keyword 'multipleOf' end end end end json-schema-2.8.0/lib/json-schema/attributes/not.rb000066400000000000000000000021551304632115000222160ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/oneof.rb000066400000000000000000000036161304632115000225270ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/pattern.rb000066400000000000000000000011631304632115000230710ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/patternproperties.rb000066400000000000000000000013451304632115000252100ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/properties.rb000066400000000000000000000051661304632115000236170ustar00rootroot00000000000000require '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 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 json-schema-2.8.0/lib/json-schema/attributes/properties_optional.rb000066400000000000000000000017171304632115000255220ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/ref.rb000066400000000000000000000044601304632115000221730ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/required.rb000066400000000000000000000020301304632115000232260ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/type.rb000066400000000000000000000057051304632115000224030ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/type_v4.rb000066400000000000000000000016121304632115000230050ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/attributes/uniqueitems.rb000066400000000000000000000007761304632115000237750ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/errors/000077500000000000000000000000001304632115000202145ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/errors/custom_format_error.rb000066400000000000000000000001311304632115000246270ustar00rootroot00000000000000module JSON class Schema class CustomFormatError < StandardError end end end json-schema-2.8.0/lib/json-schema/errors/json_load_error.rb000066400000000000000000000001251304632115000237200ustar00rootroot00000000000000module JSON class Schema class JsonLoadError < StandardError end end end json-schema-2.8.0/lib/json-schema/errors/json_parse_error.rb000066400000000000000000000001261304632115000241140ustar00rootroot00000000000000module JSON class Schema class JsonParseError < StandardError end end end json-schema-2.8.0/lib/json-schema/errors/schema_error.rb000066400000000000000000000001231304632115000232060ustar00rootroot00000000000000module JSON class Schema class SchemaError < StandardError end end end json-schema-2.8.0/lib/json-schema/errors/schema_parse_error.rb000066400000000000000000000001631304632115000244040ustar00rootroot00000000000000require 'json/common' module JSON class Schema class SchemaParseError < JSON::ParserError end end end json-schema-2.8.0/lib/json-schema/errors/uri_error.rb000066400000000000000000000001201304632115000225420ustar00rootroot00000000000000module JSON class Schema class UriError < StandardError end end end json-schema-2.8.0/lib/json-schema/errors/validation_error.rb000066400000000000000000000031371304632115000241100ustar00rootroot00000000000000module 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 json-schema-2.8.0/lib/json-schema/schema.rb000066400000000000000000000033001304632115000204610ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/schema/000077500000000000000000000000001304632115000201405ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/schema/reader.rb000066400000000000000000000106711304632115000217340ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/schema/validator.rb000066400000000000000000000022401304632115000224500ustar00rootroot00000000000000module 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 json-schema-2.8.0/lib/json-schema/util/000077500000000000000000000000001304632115000176555ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/util/array_set.rb000066400000000000000000000010111304632115000221640ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/util/uri.rb000066400000000000000000000054301304632115000210030ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/util/uuid.rb000066400000000000000000000204271304632115000211550ustar00rootroot00000000000000#!/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 endjson-schema-2.8.0/lib/json-schema/validator.rb000066400000000000000000000464441304632115000212260ustar00rootroot00000000000000require '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 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 # 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 json-schema-2.8.0/lib/json-schema/validators/000077500000000000000000000000001304632115000210505ustar00rootroot00000000000000json-schema-2.8.0/lib/json-schema/validators/draft1.rb000066400000000000000000000031241304632115000225560ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/validators/draft2.rb000066400000000000000000000032251304632115000225610ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/validators/draft3.rb000066400000000000000000000036511304632115000225650ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/validators/draft4.rb000066400000000000000000000044531304632115000225670ustar00rootroot00000000000000require '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 json-schema-2.8.0/lib/json-schema/validators/draft6.rb000066400000000000000000000044531304632115000225710ustar00rootroot00000000000000require '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-06/schema#") @names = ["draft6", "http://json-schema.org/draft-06/schema#"] @metaschema_name = "draft-06.json" end JSON::Validator.register_validator(self.new) JSON::Validator.register_default_validator(self.new) end end end json-schema-2.8.0/lib/json-schema/validators/hyper-draft1.rb000066400000000000000000000004041304632115000237010ustar00rootroot00000000000000module 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 json-schema-2.8.0/lib/json-schema/validators/hyper-draft2.rb000066400000000000000000000004041304632115000237020ustar00rootroot00000000000000module 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 json-schema-2.8.0/lib/json-schema/validators/hyper-draft3.rb000066400000000000000000000004041304632115000237030ustar00rootroot00000000000000module 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 json-schema-2.8.0/lib/json-schema/validators/hyper-draft4.rb000066400000000000000000000004041304632115000237040ustar00rootroot00000000000000module 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 json-schema-2.8.0/lib/json-schema/validators/hyper-draft6.rb000066400000000000000000000004041304632115000237060ustar00rootroot00000000000000module 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 json-schema-2.8.0/resources/000077500000000000000000000000001304632115000157355ustar00rootroot00000000000000json-schema-2.8.0/resources/draft-01.json000066400000000000000000000047131304632115000201530ustar00rootroot00000000000000{ "$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" : {} }json-schema-2.8.0/resources/draft-02.json000066400000000000000000000052441304632115000201540ustar00rootroot00000000000000{ "$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" : {} }json-schema-2.8.0/resources/draft-03.json000066400000000000000000000074271304632115000201620ustar00rootroot00000000000000{ "$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": {} } json-schema-2.8.0/resources/draft-04.json000066400000000000000000000104271304632115000201550ustar00rootroot00000000000000{ "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": {} } json-schema-2.8.0/resources/draft-06.json000066400000000000000000000104271304632115000201570ustar00rootroot00000000000000{ "id": "http://json-schema.org/draft-06/schema#", "$schema": "http://json-schema.org/draft-06/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": {} } json-schema-2.8.0/test/000077500000000000000000000000001304632115000147025ustar00rootroot00000000000000json-schema-2.8.0/test/all_of_ref_schema_test.rb000066400000000000000000000022451304632115000217010ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/any_of_ref_schema_test.rb000066400000000000000000000030741304632115000217210ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/bad_schema_ref_test.rb000066400000000000000000000025621304632115000211750ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/caching_test.rb000066400000000000000000000022231304632115000176610ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/common_test_suite_test.rb000066400000000000000000000062031304632115000220270ustar00rootroot00000000000000require File.expand_path('../support/test_helper', __FILE__) require 'json' class CommonTestSuiteTest < Minitest::Test TEST_DIR = File.expand_path('../test-suite/tests', __FILE__) # 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. IGNORED_TESTS = Hash.new { |h,k| h[k] = [] }.merge({ "draft3/optional/jsregex.json" => :all, "draft3/optional/format.json" => [ "validation of regular expressions", "validation of e-mail addresses", "validation of URIs", "validation of host names", "validation of CSS colors" ], "draft3/ref.json" => [ "ref overrides any sibling keywords/remote ref valid, maxItems ignored" ], "draft4/optional/format.json" => [ "validation of URIs", "validation of e-mail addresses", "validation of host names" ], "draft4/optional/ecmascript-regex.json" => [ "ECMA 262 regex non-compliance/ECMA 262 has no support for \\Z anchor from .NET" ], "draft4/ref.json" => [ "ref overrides any sibling keywords/remote ref valid, maxItems ignored", "ref overrides any sibling keywords/ref valid, maxItems ignored" ], "draft6/optional/format.json" => [ "validation of URIs", "validation of e-mail addresses", "validation of host names" ], "draft6/optional/ecmascript-regex.json" => [ "ECMA 262 regex non-compliance/ECMA 262 has no support for \\Z anchor from .NET" ], "draft6/ref.json" => [ "ref overrides any sibling keywords/remote ref valid, maxItems ignored", "ref overrides any sibling keywords/ref valid, maxItems ignored" ] }) 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 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| next if IGNORED_TESTS[rel_file] == :all next if IGNORED_TESTS[rel_file].any? { |ignored| base_description == ignored || "#{base_description}/#{t['description']}" == ignored } err_id = "#{rel_file}: #{base_description}/#{t['description']}" define_method("test_#{err_id}") do 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 json-schema-2.8.0/test/custom_format_test.rb000066400000000000000000000126351304632115000211570ustar00rootroot00000000000000# 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-06/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 json-schema-2.8.0/test/data/000077500000000000000000000000001304632115000156135ustar00rootroot00000000000000json-schema-2.8.0/test/data/all_of_ref_data.json000066400000000000000000000000261304632115000215650ustar00rootroot00000000000000{ "name" : "john" } json-schema-2.8.0/test/data/any_of_ref_data.json000066400000000000000000000000761304632115000216110ustar00rootroot00000000000000{ "names" : [ "john" , "jane" , "jimmy" ] } json-schema-2.8.0/test/data/bad_data_1.json000066400000000000000000000000221304632115000204370ustar00rootroot00000000000000{ "a" : "poop" }json-schema-2.8.0/test/data/good_data_1.json000066400000000000000000000000151304632115000206430ustar00rootroot00000000000000{ "a" : 5 }json-schema-2.8.0/test/data/one_of_ref_links_data.json000066400000000000000000000002331304632115000227760ustar00rootroot00000000000000{ "links": [{ "rel" : ["self"] , "href":"http://api.example.com/api/object/3" } ,{ "rel" : ["up"] , "href":"http://api.example.com/api/object" } ] } json-schema-2.8.0/test/draft1_test.rb000066400000000000000000000055571304632115000174630ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/draft2_test.rb000066400000000000000000000047761304632115000174660ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/draft3_test.rb000066400000000000000000000302011304632115000174450ustar00rootroot00000000000000# 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 json-schema-2.8.0/test/draft4_test.rb000066400000000000000000000416211304632115000174560ustar00rootroot00000000000000# 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 json-schema-2.8.0/test/extended_schema_test.rb000066400000000000000000000034601304632115000214110ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/extends_nested_test.rb000066400000000000000000000026241304632115000213060ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/files_test.rb000066400000000000000000000043331304632115000173730ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/fragment_resolution_test.rb000066400000000000000000000014451304632115000223600ustar00rootroot00000000000000require 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 end json-schema-2.8.0/test/fragment_validation_with_ref_test.rb000066400000000000000000000014771304632115000242030ustar00rootroot00000000000000require 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 test_validation_of_fragment data = [{"content" => "ohai", "author" => "Bob"}] assert_valid whole_schema, data, :fragment => "#/definitions/posts" end end json-schema-2.8.0/test/full_validation_test.rb000066400000000000000000000116231304632115000214450ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/initialize_data_test.rb000066400000000000000000000073631304632115000214310ustar00rootroot00000000000000require 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_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_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 json-schema-2.8.0/test/list_option_test.rb000066400000000000000000000011471304632115000206340ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/load_ref_schema_test.rb000066400000000000000000000022061304632115000213610ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/merge_missing_values_test.rb000066400000000000000000000033411304632115000224760ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/min_items_test.rb000066400000000000000000000006241304632115000202540ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/one_of_test.rb000066400000000000000000000054231304632115000175370ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/relative_definition_test.rb000066400000000000000000000010651304632115000223130ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/ruby_schema_test.rb000066400000000000000000000024101304632115000205640ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/schema_reader_test.rb000066400000000000000000000046501304632115000210550ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/schema_validation_test.rb000066400000000000000000000110131304632115000217340ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/schemas/000077500000000000000000000000001304632115000163255ustar00rootroot00000000000000json-schema-2.8.0/test/schemas/address_microformat.json000066400000000000000000000012001304632115000232400ustar00rootroot00000000000000{ "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" } } json-schema-2.8.0/test/schemas/all_of_ref_base_schema.json000066400000000000000000000001211304632115000236140ustar00rootroot00000000000000{ "type": "object", "properties" : { "name" : { "type": "integer" } } } json-schema-2.8.0/test/schemas/all_of_ref_schema.json000066400000000000000000000002201304632115000226220ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#", "type" : "object", "allOf" : [ { "$ref" : "all_of_ref_base_schema.json" } ] } json-schema-2.8.0/test/schemas/any_of_ref_jane_schema.json000066400000000000000000000001431304632115000236420ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "jane" } json-schema-2.8.0/test/schemas/any_of_ref_jimmy_schema.json000066400000000000000000000001441304632115000240530ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "jimmy" } json-schema-2.8.0/test/schemas/any_of_ref_john_schema.json000066400000000000000000000001431304632115000236630ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "john" } json-schema-2.8.0/test/schemas/any_of_ref_schema.json000066400000000000000000000005421304632115000226500ustar00rootroot00000000000000{ "$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" } ] } } } } json-schema-2.8.0/test/schemas/definition_schema.json000066400000000000000000000004071304632115000226710ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "description": "schema with definition", "type": "object", "properties": { "a": { "$ref": "#/definitions/foo" } }, "definitions": { "foo": { "type": "integer" } } } json-schema-2.8.0/test/schemas/definition_schema_with_special_characters.json000066400000000000000000000003441304632115000276230ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "a": { "$ref": "#/definitions/foo:bar" } }, "definitions": { "foo:bar": { "type": "integer" } } } json-schema-2.8.0/test/schemas/extends_and_additionalProperties_false_schema.json000066400000000000000000000011001304632115000304430ustar00rootroot00000000000000{ "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 } json-schema-2.8.0/test/schemas/extends_and_patternProperties_schema.json000066400000000000000000000010461304632115000266470ustar00rootroot00000000000000{ "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" } } } json-schema-2.8.0/test/schemas/good_schema_1.json000066400000000000000000000001601304632115000217050ustar00rootroot00000000000000{ "type" : "object", "properties" : { "a" : { "type" : "integer" } }, "required": ["a"] } json-schema-2.8.0/test/schemas/good_schema_2.json000066400000000000000000000001731304632115000217120ustar00rootroot00000000000000{ "type" : "object", "properties" : { "b" : { "$ref" : "good_schema_1.json" } }, "required": ["b"] } json-schema-2.8.0/test/schemas/good_schema_extends1.json000066400000000000000000000001571304632115000233060ustar00rootroot00000000000000{ "type" : "object", "extends": {"$ref": "good_schema_1.json"}, "properties" : { "c" : { } } } json-schema-2.8.0/test/schemas/good_schema_extends2.json000066400000000000000000000002351304632115000233040ustar00rootroot00000000000000{ "type" : "object", "extends": [ {"$ref": "good_schema_1.json"}, {"$ref": "good_schema_2.json"} ], "properties" : { "c" : { } } } json-schema-2.8.0/test/schemas/inner_schema.json000066400000000000000000000004171304632115000216550ustar00rootroot00000000000000{ "type": "object", "properties": { "innerA": { "description": "blah", "type":"boolean" }, "innerB": { "description": "blah", "type":"boolean" }, "innerC": { "description": "blah", "type": "boolean" } } } json-schema-2.8.0/test/schemas/one_of_ref_links_schema.json000066400000000000000000000004651304632115000240460ustar00rootroot00000000000000{ "$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" } ] } } } } json-schema-2.8.0/test/schemas/ref john with spaces schema.json000066400000000000000000000003061304632115000243260ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#", "type" : "object", "required" : ["first"], "properties": { "first": { "type": "string", "enum": ["john"] } } } json-schema-2.8.0/test/schemas/relative_definition_schema.json000066400000000000000000000002321304632115000245600ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "a": { "$ref": "definition_schema.json#/definitions/foo" } } }json-schema-2.8.0/test/schemas/self_link_schema.json000066400000000000000000000004211304632115000225030ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties" : { "rel" : { "type" : "array" , "items" : [ { "type" : "string" , "pattern" : "self" } ] } , "href" : { "type" : "string" } } } json-schema-2.8.0/test/schemas/up_link_schema.json000066400000000000000000000004171304632115000222030ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties" : { "rel" : { "type" : "array" , "items" : [ { "type" : "string" , "pattern" : "up" } ] } , "href" : { "type" : "string" } } } json-schema-2.8.0/test/stringify_test.rb000066400000000000000000000024071304632115000203070ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/support/000077500000000000000000000000001304632115000164165ustar00rootroot00000000000000json-schema-2.8.0/test/support/array_validation.rb000066400000000000000000000051641304632115000223010ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/support/enum_validation.rb000066400000000000000000000047521304632115000221310ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/support/number_validation.rb000066400000000000000000000034331304632115000224500ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/support/object_validation.rb000066400000000000000000000034561304632115000224330ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/support/strict_validation.rb000066400000000000000000000053651304632115000224760ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/support/string_validation.rb000066400000000000000000000100251304632115000224610ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/support/test_helper.rb000066400000000000000000000024001304632115000212550ustar00rootroot00000000000000require '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 json-schema-2.8.0/test/support/type_validation.rb000066400000000000000000000040261304632115000221400ustar00rootroot00000000000000module 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 json-schema-2.8.0/test/test-suite/000077500000000000000000000000001304632115000170105ustar00rootroot00000000000000json-schema-2.8.0/test/type_attribute_test.rb000066400000000000000000000011611304632115000213310ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/uri_parsing_test.rb000066400000000000000000000032411304632115000206100ustar00rootroot00000000000000# 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 json-schema-2.8.0/test/uri_util_test.rb000066400000000000000000000170301304632115000201230ustar00rootroot00000000000000require 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 json-schema-2.8.0/test/validator_schema_reader_test.rb000066400000000000000000000030331304632115000231140ustar00rootroot00000000000000require 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