pax_global_header00006660000000000000000000000064151525107410014513gustar00rootroot0000000000000052 comment=67b1e22d82e6e24e01034a1f9644a8dbfc88734e voxpupuli-json-schema-9b1349a/000077500000000000000000000000001515251074100163315ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/.github/000077500000000000000000000000001515251074100176715ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/.github/dependabot.yml000066400000000000000000000005751515251074100225300ustar00rootroot00000000000000version: 2 updates: # raise PRs for gem updates - package-ecosystem: bundler directory: "/" schedule: interval: daily time: "13:00" open-pull-requests-limit: 10 # Maintain dependencies for GitHub Actions - package-ecosystem: github-actions directory: "/" schedule: interval: daily time: "13:00" open-pull-requests-limit: 10 voxpupuli-json-schema-9b1349a/.github/release.yml000066400000000000000000000013731515251074100220400ustar00rootroot00000000000000--- # https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes changelog: exclude: labels: - duplicate - invalid - modulesync - question - skip-changelog - wont-fix - wontfix - github_actions categories: - title: Breaking Changes πŸ›  labels: - backwards-incompatible - title: New Features πŸŽ‰ labels: - enhancement - title: Bug Fixes πŸ› labels: - bug - bugfix - title: Documentation Updates πŸ“š labels: - documentation - docs - title: Dependency Updates ⬆️ labels: - dependencies - title: Other Changes labels: - "*" voxpupuli-json-schema-9b1349a/.github/workflows/000077500000000000000000000000001515251074100217265ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/.github/workflows/release.yml000066400000000000000000000055761515251074100241060ustar00rootroot00000000000000--- name: Gem Release on: push: tags: - '*' permissions: {} jobs: build-release: # Prevent releases from forked repositories if: github.repository_owner == 'voxpupuli' name: Build the gem runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - name: Install Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 'ruby' - name: Build gem shell: bash run: gem build --verbose *.gemspec - name: Upload gem to GitHub cache uses: actions/upload-artifact@v7 with: name: gem-artifact path: '*.gem' retention-days: 1 compression-level: 0 create-github-release: needs: build-release name: Create GitHub release runs-on: ubuntu-24.04 permissions: contents: write # clone repo and create release steps: - name: Download gem from GitHub cache uses: actions/download-artifact@v8 with: name: gem-artifact - name: Create Release shell: bash env: GH_TOKEN: ${{ github.token }} run: gh release create --repo ${{ github.repository }} ${{ github.ref_name }} --generate-notes *.gem release-to-github: needs: build-release name: Release to GitHub runs-on: ubuntu-24.04 permissions: packages: write # publish to rubygems.pkg.github.com steps: - name: Download gem from GitHub cache uses: actions/download-artifact@v8 with: name: gem-artifact - name: Publish gem to GitHub packages run: gem push --host https://rubygems.pkg.github.com/${{ github.repository_owner }} *.gem env: GEM_HOST_API_KEY: ${{ secrets.GITHUB_TOKEN }} release-to-rubygems: needs: build-release name: Release gem to rubygems.org runs-on: ubuntu-24.04 environment: release # recommended by rubygems.org permissions: id-token: write # rubygems.org authentication steps: - name: Download gem from GitHub cache uses: actions/download-artifact@v8 with: name: gem-artifact - uses: rubygems/configure-rubygems-credentials@v1.0.0 - name: Publish gem to rubygems.org shell: bash run: gem push *.gem release-verification: name: Check that all releases are done runs-on: ubuntu-24.04 permissions: contents: read # minimal permissions that we have to grant needs: - create-github-release - release-to-github - release-to-rubygems steps: - name: Download gem from GitHub cache uses: actions/download-artifact@v8 with: name: gem-artifact - name: Install Ruby uses: ruby/setup-ruby@v1 with: ruby-version: 'ruby' - name: Wait for release to propagate shell: bash run: | gem install rubygems-await gem await *.gem voxpupuli-json-schema-9b1349a/.github/workflows/test.yml000066400000000000000000000023551515251074100234350ustar00rootroot00000000000000--- name: Test on: pull_request: {} push: branches: - master permissions: contents: read jobs: test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - ruby: truffleruby - ruby: truffleruby+graalvm - ruby: jruby - ruby: "2.7" - ruby: "3.0" - ruby: "3.1" - ruby: "3.2" rake_task: "rubocop test" - ruby: "3.3" - ruby: "3.3" rubyopt: "--enable-frozen-string-literal" - ruby: "3.4" - ruby: "4.0" steps: - uses: actions/checkout@v6 - name: Install Ruby ${{ matrix.ruby }} uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run tests run: bundle exec rake ${{ matrix.rake_task }} RUBYOPT="${{ matrix.rubyopt }}" - name: Build gem run: gem build --strict --verbose *.gemspec tests: if: always() needs: - test runs-on: ubuntu-24.04 name: Test suite steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} voxpupuli-json-schema-9b1349a/.gitignore000066400000000000000000000001221515251074100203140ustar00rootroot00000000000000/.project .*.swp pkg *.gem /Gemfile.lock .bundle .idea /coverage /vendor /.vendor voxpupuli-json-schema-9b1349a/.gitmodules000066400000000000000000000002121515251074100205010ustar00rootroot00000000000000[submodule "test/test-suite"] path = test/test-suite branch = master url = git://github.com/json-schema-org/JSON-Schema-Test-Suite.git voxpupuli-json-schema-9b1349a/.rubocop.yml000066400000000000000000000001651515251074100206050ustar00rootroot00000000000000--- inherit_from: .rubocop_todo.yml inherit_gem: voxpupuli-rubocop: rubocop.yml AllCops: TargetRubyVersion: 2.7 voxpupuli-json-schema-9b1349a/.rubocop_todo.yml000066400000000000000000000212101515251074100216240ustar00rootroot00000000000000# This configuration was generated by # `rubocop --auto-gen-config --no-auto-gen-timestamp` # using RuboCop version 1.79.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: RequireParenthesesForMethodChains. Lint/AmbiguousRange: Exclude: - 'test/common_test_suite_test.rb' # Offense count: 4 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowSafeAssignment. Lint/AssignmentInCondition: Exclude: - 'lib/json-schema/attributes/additionalproperties.rb' - 'lib/json-schema/attributes/disallow.rb' - 'lib/json-schema/validator.rb' # Offense count: 1 # Configuration parameters: AllowedParentClasses. Lint/MissingSuper: Exclude: - 'lib/json-schema/attributes/formats/custom.rb' # Offense count: 2 # Configuration parameters: AllowComments, AllowNil. Lint/SuppressedException: Exclude: - 'Rakefile' - 'lib/json-schema/validator.rb' # Offense count: 63 Minitest/MultipleAssertions: Max: 25 # Offense count: 100 # This cop supports unsafe autocorrection (--autocorrect-all). Minitest/RefuteFalse: Exclude: - 'test/custom_format_test.rb' - 'test/draft3_test.rb' - 'test/draft4_test.rb' - 'test/schema_validation_test.rb' - 'test/support/strict_validation.rb' # Offense count: 1 Naming/AccessorMethodName: Exclude: - 'test/caching_test.rb' # Offense count: 2 # Configuration parameters: AllowedNames. # AllowedNames: module_parent Naming/ClassAndModuleCamelCase: Exclude: - 'test/support/enum_validation.rb' # Offense count: 6 # Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. # CheckDefinitionPathHierarchyRoots: lib, spec, test, src # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS Naming/FileName: Exclude: - 'Rakefile.rb' - 'lib/json-schema.rb' - 'lib/json-schema/validators/hyper-draft1.rb' - 'lib/json-schema/validators/hyper-draft2.rb' - 'lib/json-schema/validators/hyper-draft3.rb' - 'lib/json-schema/validators/hyper-draft4.rb' - 'lib/json-schema/validators/hyper-draft6.rb' # Offense count: 16 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: Exclude: - 'lib/json-schema/attributes/extends.rb' - 'lib/json-schema/attributes/ref.rb' - 'lib/json-schema/util/uuid.rb' - 'lib/json-schema/validator.rb' # Offense count: 18 # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns. # SupportedStyles: snake_case, normalcase, non_integer # AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64 Naming/VariableNumber: Exclude: - 'test/all_of_ref_schema_test.rb' - 'test/any_of_ref_schema_test.rb' - 'test/custom_format_test.rb' - 'test/one_of_test.rb' # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: SafeMultiline. Performance/DeletePrefix: Exclude: - 'lib/json-schema/util/uuid.rb' # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). Performance/RangeInclude: Exclude: - 'lib/json-schema/util/uuid.rb' # Offense count: 1 Security/MarshalLoad: Exclude: - 'lib/json-schema/util/uuid.rb' # Offense count: 4 Security/Open: Exclude: - 'lib/json-schema/schema/reader.rb' - 'lib/json-schema/util/uuid.rb' - 'lib/json-schema/validator.rb' # Offense count: 21 Style/ClassVars: Exclude: - 'lib/json-schema/validator.rb' # Offense count: 70 # Configuration parameters: AllowedConstants. Style/Documentation: Enabled: false # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: format, sprintf, percent Style/FormatString: Exclude: - 'lib/json-schema/util/uuid.rb' # Offense count: 21 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns. # SupportedStyles: annotated, template, unannotated Style/FormatStringToken: EnforcedStyle: unannotated # Offense count: 118 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: Enabled: false # Offense count: 24 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: Enabled: false # Offense count: 5 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowedReceivers. # AllowedReceivers: Thread.current Style/HashEachMethods: Exclude: - 'lib/json-schema/attributes/patternproperties.rb' - 'lib/json-schema/attributes/properties.rb' - 'lib/json-schema/attributes/required.rb' - 'lib/json-schema/schema/validator.rb' - 'lib/json-schema/validator.rb' # Offense count: 19 # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Exclude: - 'Rakefile' - 'lib/json-schema/attributes/additionalproperties.rb' - 'lib/json-schema/attributes/not.rb' - 'lib/json-schema/attributes/ref.rb' - 'lib/json-schema/schema.rb' - 'lib/json-schema/schema/validator.rb' - 'lib/json-schema/validator.rb' # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). Style/MapToHash: Exclude: - 'lib/json-schema/schema.rb' # Offense count: 1 Style/MultilineBlockChain: Exclude: - 'lib/json-schema/attribute.rb' # Offense count: 8 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: literals, strict Style/MutableConstant: Exclude: - 'lib/json-schema/attribute.rb' - 'lib/json-schema/errors/validation_error.rb' - 'lib/json-schema/util/uri.rb' - 'lib/json-schema/util/uuid.rb' - 'test/extends_nested_test.rb' - 'test/schema_reader_test.rb' - 'test/support/type_validation.rb' # Offense count: 10 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: - 'spec/**/*' - 'lib/json-schema/attributes/allof.rb' - 'lib/json-schema/attributes/anyof.rb' - 'lib/json-schema/attributes/divisibleby.rb' - 'lib/json-schema/attributes/oneof.rb' - 'lib/json-schema/attributes/type.rb' - 'lib/json-schema/errors/validation_error.rb' - 'test/extended_schema_test.rb' # Offense count: 2 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - 'lib/json-schema/validator.rb' # Offense count: 10 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: short, verbose Style/PreferredHashMethods: Exclude: - 'lib/json-schema/attributes/dependencies.rb' - 'lib/json-schema/attributes/properties.rb' - 'lib/json-schema/attributes/properties_optional.rb' - 'lib/json-schema/attributes/required.rb' - 'lib/json-schema/schema/validator.rb' # Offense count: 4 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Mode. Style/StringConcatenation: Exclude: - 'lib/json-schema/attributes/ref.rb' - 'lib/json-schema/util/uuid.rb' - 'test/schema_reader_test.rb' # Offense count: 3 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. # AllowedMethods: define_method Style/SymbolProc: Exclude: - 'lib/json-schema/errors/validation_error.rb' - 'lib/json-schema/validator.rb' # Offense count: 71 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: Max: 235 voxpupuli-json-schema-9b1349a/CHANGELOG.md000066400000000000000000001615221515251074100201510ustar00rootroot00000000000000# Changelog ## [v6.2.0](https://github.com/voxpupuli/json-schema/tree/v6.2.0) (2026-03-06) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v6.1.0...v6.2.0) **Implemented enhancements:** - Allow disabling MultiJSON even when it is installed [\#566](https://github.com/voxpupuli/json-schema/pull/566) ([jordan-brough](https://github.com/jordan-brough)) - Add Ruby 4.0 support [\#564](https://github.com/voxpupuli/json-schema/pull/564) ([bastelfreak](https://github.com/bastelfreak)) - Restore support for Ruby 2.7 – Ruby 3.1 [\#561](https://github.com/voxpupuli/json-schema/pull/561) ([koic](https://github.com/koic)) ## [v6.1.0](https://github.com/voxpupuli/json-schema/tree/v6.1.0) (2025-12-21) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v6.0.0...v6.1.0) **Implemented enhancements:** - voxpupuli-rubocop: Update 4.2.0-\>5.1.0 [\#559](https://github.com/voxpupuli/json-schema/pull/559) ([bastelfreak](https://github.com/bastelfreak)) - minitest: Allow 6.x [\#558](https://github.com/voxpupuli/json-schema/pull/558) ([bastelfreak](https://github.com/bastelfreak)) - bigdecimal: Allow 4.x [\#557](https://github.com/voxpupuli/json-schema/pull/557) ([bastelfreak](https://github.com/bastelfreak)) ## [v6.0.0](https://github.com/voxpupuli/json-schema/tree/v6.0.0) (2025-08-12) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.2.2...v6.0.0) **Breaking changes:** - Require Ruby 3.2 or newer [\#549](https://github.com/voxpupuli/json-schema/pull/549) ([bastelfreak](https://github.com/bastelfreak)) ## [v5.2.2](https://github.com/voxpupuli/json-schema/tree/v5.2.2) (2025-08-12) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.2.1...v5.2.2) **Fixed bugs:** - Improve :failed\_attribute value for custom formats [\#545](https://github.com/voxpupuli/json-schema/pull/545) ([bmdelaune](https://github.com/bmdelaune)) ## [v5.2.1](https://github.com/voxpupuli/json-schema/tree/v5.2.1) (2025-07-09) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.2.0...v5.2.1) **Fixed bugs:** - Require delegate library in validator [\#542](https://github.com/voxpupuli/json-schema/pull/542) ([beechtom](https://github.com/beechtom)) ## [v5.2.0](https://github.com/voxpupuli/json-schema/tree/v5.2.0) (2025-07-09) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.1.1...v5.2.0) **Implemented enhancements:** - Add Ruby 3.4 to CI & drop coverage reporting [\#539](https://github.com/voxpupuli/json-schema/pull/539) ([bastelfreak](https://github.com/bastelfreak)) - Make JSON::Validator freezable [\#537](https://github.com/voxpupuli/json-schema/pull/537) ([hugopeixoto](https://github.com/hugopeixoto)) **Fixed bugs:** - Fixes `allOf` bug when using `noAdditionalProperties` option [\#535](https://github.com/voxpupuli/json-schema/pull/535) ([azrosen92](https://github.com/azrosen92)) ## [v5.1.1](https://github.com/voxpupuli/json-schema/tree/v5.1.1) (2024-12-02) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.1.0...v5.1.1) **Fixed bugs:** - Add bigdecimal dependency to fix deprecation warning for Ruby 3.4 [\#533](https://github.com/voxpupuli/json-schema/pull/533) ([jamiecobbett](https://github.com/jamiecobbett)) ## [v5.1.0](https://github.com/voxpupuli/json-schema/tree/v5.1.0) (2024-11-20) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.0.1...v5.1.0) **Implemented enhancements:** - Add funding\_uri to gemspec [\#530](https://github.com/voxpupuli/json-schema/pull/530) ([andrew](https://github.com/andrew)) **Fixed bugs:** - Update license reference [\#529](https://github.com/voxpupuli/json-schema/pull/529) ([emmanuel-ferdman](https://github.com/emmanuel-ferdman)) **Merged pull requests:** - voxpupuli-rubocop: Update 2.8.0-\>3.0.0 & rubocop: autofix [\#531](https://github.com/voxpupuli/json-schema/pull/531) ([bastelfreak](https://github.com/bastelfreak)) ## [v5.0.1](https://github.com/voxpupuli/json-schema/tree/v5.0.1) (2024-10-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v5.0.0...v5.0.1) **Fixed bugs:** - Load rake tasks from voxpupuli-rubocop [\#527](https://github.com/voxpupuli/json-schema/pull/527) ([bastelfreak](https://github.com/bastelfreak)) ## [v5.0.0](https://github.com/voxpupuli/json-schema/tree/v5.0.0) (2024-08-19) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v4.3.1...v5.0.0) **Breaking changes:** - Drop Ruby 2.5/2.6 support [\#521](https://github.com/voxpupuli/json-schema/pull/521) ([bastelfreak](https://github.com/bastelfreak)) - Fix caching issues in JSON::Util::URI [\#515](https://github.com/voxpupuli/json-schema/pull/515) ([bolshakov](https://github.com/bolshakov)) **Implemented enhancements:** - Drop Ruby 1.8 leftovers [\#519](https://github.com/voxpupuli/json-schema/pull/519) ([bastelfreak](https://github.com/bastelfreak)) - Switch to latest voxpupuli-rubocop [\#478](https://github.com/voxpupuli/json-schema/pull/478) ([bastelfreak](https://github.com/bastelfreak)) **Merged pull requests:** - dev deps: Add strict version contraints & CI: build gem with strict mode & CI: Use Ruby 3.3 for releases [\#525](https://github.com/voxpupuli/json-schema/pull/525) ([bastelfreak](https://github.com/bastelfreak)) - Drop bundler dev dependency [\#524](https://github.com/voxpupuli/json-schema/pull/524) ([bastelfreak](https://github.com/bastelfreak)) - .gitignore: Add vendor dirs from bundler [\#523](https://github.com/voxpupuli/json-schema/pull/523) ([bastelfreak](https://github.com/bastelfreak)) - Update "Understanding JSON Schemas" URL in README.md [\#522](https://github.com/voxpupuli/json-schema/pull/522) ([yohasebe](https://github.com/yohasebe)) - Remove VERSION.yml [\#520](https://github.com/voxpupuli/json-schema/pull/520) ([bastelfreak](https://github.com/bastelfreak)) ## [v4.3.1](https://github.com/voxpupuli/json-schema/tree/v4.3.1) (2024-07-12) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v4.3.0...v4.3.1) **Fixed bugs:** - Add missing require 'stringio' [\#512](https://github.com/voxpupuli/json-schema/pull/512) ([jmarrec](https://github.com/jmarrec)) ## [v4.3.0](https://github.com/voxpupuli/json-schema/tree/v4.3.0) (2024-03-26) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v4.2.0...v4.3.0) **Implemented enhancements:** - json-schema.gemspec: add metadata links [\#510](https://github.com/voxpupuli/json-schema/pull/510) ([olleolleolle](https://github.com/olleolleolle)) ## [v4.2.0](https://github.com/voxpupuli/json-schema/tree/v4.2.0) (2024-03-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v4.1.1...v4.2.0) **Implemented enhancements:** - Ensure compatibility with `ruby --enable-frozen-string-literal` [\#508](https://github.com/voxpupuli/json-schema/pull/508) ([casperisfine](https://github.com/casperisfine)) ## [v4.1.1](https://github.com/voxpupuli/json-schema/tree/v4.1.1) (2023-09-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v4.1.0...v4.1.1) **Merged pull requests:** - Add dummy CI job we can depend on [\#503](https://github.com/voxpupuli/json-schema/pull/503) ([bastelfreak](https://github.com/bastelfreak)) - dependabot: check for github actions and gems [\#501](https://github.com/voxpupuli/json-schema/pull/501) ([bastelfreak](https://github.com/bastelfreak)) ## [v4.1.0](https://github.com/voxpupuli/json-schema/tree/v4.1.0) (2023-09-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v4.0.0...v4.1.0) **Implemented enhancements:** - Add `allPropertiesRequired` and `noAdditionalProperties` options [\#494](https://github.com/voxpupuli/json-schema/pull/494) ([a-lavis](https://github.com/a-lavis)) **Fixed bugs:** - Integer as string should be defined as string [\#497](https://github.com/voxpupuli/json-schema/pull/497) ([mohanapriya2308](https://github.com/mohanapriya2308)) - Handling allOf error message [\#495](https://github.com/voxpupuli/json-schema/pull/495) ([anupama-kumari](https://github.com/anupama-kumari)) ## [v4.0.0](https://github.com/voxpupuli/json-schema/tree/v4.0.0) (2023-04-24) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v3.0.0...v4.0.0) **Breaking changes:** - Removed `data` ivar from JSON::Validator so that multiple `validate` call become faster [\#465](https://github.com/voxpupuli/json-schema/pull/465) ([ganmacs](https://github.com/ganmacs)) **Implemented enhancements:** - Fix more rubocop violations [\#484](https://github.com/voxpupuli/json-schema/pull/484) ([bastelfreak](https://github.com/bastelfreak)) - Fix multiple rubocop violations [\#483](https://github.com/voxpupuli/json-schema/pull/483) ([bastelfreak](https://github.com/bastelfreak)) - Add Ruby 3.2 to CI matrix [\#482](https://github.com/voxpupuli/json-schema/pull/482) ([bastelfreak](https://github.com/bastelfreak)) - Enable RuboCop in CI [\#480](https://github.com/voxpupuli/json-schema/pull/480) ([bastelfreak](https://github.com/bastelfreak)) - docs: mention draft 06 support [\#476](https://github.com/voxpupuli/json-schema/pull/476) ([levenleven](https://github.com/levenleven)) - Add const validator to draft6. [\#425](https://github.com/voxpupuli/json-schema/pull/425) ([torce](https://github.com/torce)) - Add propertyNames validator to draft6 [\#407](https://github.com/voxpupuli/json-schema/pull/407) ([torce](https://github.com/torce)) **Fixed bugs:** - Changed draft-06 url back from /draft/schema\# to /draft-06/schema\# [\#388](https://github.com/voxpupuli/json-schema/pull/388) ([iainbeeston](https://github.com/iainbeeston)) **Merged pull requests:** - fix more rubocop violations [\#490](https://github.com/voxpupuli/json-schema/pull/490) ([bastelfreak](https://github.com/bastelfreak)) - fix rubocop whitespace violations [\#489](https://github.com/voxpupuli/json-schema/pull/489) ([bastelfreak](https://github.com/bastelfreak)) - Fix more rubocop violations [\#488](https://github.com/voxpupuli/json-schema/pull/488) ([bastelfreak](https://github.com/bastelfreak)) - rubocop: Fix Style/HashSyntax [\#487](https://github.com/voxpupuli/json-schema/pull/487) ([bastelfreak](https://github.com/bastelfreak)) - CI: Run on PRs and merges to master [\#486](https://github.com/voxpupuli/json-schema/pull/486) ([bastelfreak](https://github.com/bastelfreak)) - rubocop: Fix Style/StringLiterals [\#485](https://github.com/voxpupuli/json-schema/pull/485) ([bastelfreak](https://github.com/bastelfreak)) - CI: Only run on pull requests & Use latest GitHub workflows [\#481](https://github.com/voxpupuli/json-schema/pull/481) ([bastelfreak](https://github.com/bastelfreak)) ## [v3.0.0](https://github.com/voxpupuli/json-schema/tree/v3.0.0) (2022-05-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.8.1...v3.0.0) **Breaking changes:** - json-schema.gemspec: Raise required ruby version to 2.5 [\#466](https://github.com/voxpupuli/json-schema/pull/466) ([bastelfreak](https://github.com/bastelfreak)) - Call URI.open directly / Drop Ruby 2.4 support [\#462](https://github.com/voxpupuli/json-schema/pull/462) ([bastelfreak](https://github.com/bastelfreak)) **Implemented enhancements:** - Add const attribute support [\#471](https://github.com/voxpupuli/json-schema/pull/471) ([jeremie-stripe](https://github.com/jeremie-stripe)) - Add truffleruby/jruby to CI [\#469](https://github.com/voxpupuli/json-schema/pull/469) ([bastelfreak](https://github.com/bastelfreak)) - Add Ruby 3.1 to CI matrix [\#468](https://github.com/voxpupuli/json-schema/pull/468) ([bastelfreak](https://github.com/bastelfreak)) - Add Ruby 3.0 to CI matrix [\#467](https://github.com/voxpupuli/json-schema/pull/467) ([bastelfreak](https://github.com/bastelfreak)) - Allow resolution of fragments with escaped parts [\#463](https://github.com/voxpupuli/json-schema/pull/463) ([bastelfreak](https://github.com/bastelfreak)) - Add Ruby 2.6/2.7 support [\#457](https://github.com/voxpupuli/json-schema/pull/457) ([bastelfreak](https://github.com/bastelfreak)) **Fixed bugs:** - Bugfix: Fix fragment when used with extended schema [\#464](https://github.com/voxpupuli/json-schema/pull/464) ([bastelfreak](https://github.com/bastelfreak)) **Closed issues:** - Failure/Error: require 'json-schema-rspec', cannot load such file -- multi\_json [\#448](https://github.com/voxpupuli/json-schema/issues/448) - Allow type or null? [\#441](https://github.com/voxpupuli/json-schema/issues/441) - type for NilClass [\#428](https://github.com/voxpupuli/json-schema/issues/428) - It would be very useful if the required property name was included in the error object [\#417](https://github.com/voxpupuli/json-schema/issues/417) - Uninitialized constant JSON::Validator::Timeout [\#384](https://github.com/voxpupuli/json-schema/issues/384) **Merged pull requests:** - update README.md/gemspec; migrate to GitHub actions [\#456](https://github.com/voxpupuli/json-schema/pull/456) ([bastelfreak](https://github.com/bastelfreak)) - Update json-schema.gemspec; require addressable 2.8 and newer [\#455](https://github.com/voxpupuli/json-schema/pull/455) ([ahsandar](https://github.com/ahsandar)) - Update README.md [\#444](https://github.com/voxpupuli/json-schema/pull/444) ([cagmz](https://github.com/cagmz)) - Load VERSION.yml from relative path, so that developers can use "bundle config local.json-schema" [\#419](https://github.com/voxpupuli/json-schema/pull/419) ([ndbroadbent](https://github.com/ndbroadbent)) - Fix typo in Changelog \(2019 =\> 2018\) [\#418](https://github.com/voxpupuli/json-schema/pull/418) ([ndbroadbent](https://github.com/ndbroadbent)) - Made sure we require timeout before using it [\#385](https://github.com/voxpupuli/json-schema/pull/385) ([iainbeeston](https://github.com/iainbeeston)) - webmock 3 drops ruby 1.9 support; specify this in its gemfile [\#383](https://github.com/voxpupuli/json-schema/pull/383) ([notEthan](https://github.com/notEthan)) - Refactor common test suite [\#377](https://github.com/voxpupuli/json-schema/pull/377) ([iainbeeston](https://github.com/iainbeeston)) - Corrected the draf6 schema id [\#376](https://github.com/voxpupuli/json-schema/pull/376) ([iainbeeston](https://github.com/iainbeeston)) - Added a rake task to automatically download the latest metaschemas [\#375](https://github.com/voxpupuli/json-schema/pull/375) ([iainbeeston](https://github.com/iainbeeston)) - Re-enabled test warnings [\#374](https://github.com/voxpupuli/json-schema/pull/374) ([iainbeeston](https://github.com/iainbeeston)) - Fix for string invalid scheme error when string contains colon [\#373](https://github.com/voxpupuli/json-schema/pull/373) ([benSlaughter](https://github.com/benSlaughter)) - Added simplecov [\#343](https://github.com/voxpupuli/json-schema/pull/343) ([iainbeeston](https://github.com/iainbeeston)) - Extracted all limits out to their own file [\#342](https://github.com/voxpupuli/json-schema/pull/342) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.8.1](https://github.com/voxpupuli/json-schema/tree/v2.8.1) (2018-10-14) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.8.0...v2.8.1) **Closed issues:** - Version 2.8.1 Patch release? [\#415](https://github.com/voxpupuli/json-schema/issues/415) - possible to enforce schema ? [\#410](https://github.com/voxpupuli/json-schema/issues/410) - undefined method `each' for "\":String [\#409](https://github.com/voxpupuli/json-schema/issues/409) - Documentation Request: How do I validate the schema itself? [\#398](https://github.com/voxpupuli/json-schema/issues/398) - :errors\_as\_objects can never be false in base\_schema.validate [\#392](https://github.com/voxpupuli/json-schema/issues/392) - too complex [\#390](https://github.com/voxpupuli/json-schema/issues/390) - Release 2.8.0 of the gem is missing a tag in the repo [\#389](https://github.com/voxpupuli/json-schema/issues/389) - Remove trailing whitespaces [\#378](https://github.com/voxpupuli/json-schema/issues/378) - Failure on 'allOf' validation message output is too generic [\#320](https://github.com/voxpupuli/json-schema/issues/320) ## [v2.8.0](https://github.com/voxpupuli/json-schema/tree/v2.8.0) (2017-02-07) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.7.0...v2.8.0) **Closed issues:** - JSON::Validator.fully\_validate\(filename, data\) fails when trying to parse filename as JSON [\#366](https://github.com/voxpupuli/json-schema/issues/366) - 2.7.0 fails validating not required fields [\#364](https://github.com/voxpupuli/json-schema/issues/364) - Unable to activate json-schema-2.6.2, because addressable-2.4.0 conflicts with addressable \(~\> 2.3.8\) [\#356](https://github.com/voxpupuli/json-schema/issues/356) - Missing comma after empty array not detected as invalid [\#352](https://github.com/voxpupuli/json-schema/issues/352) - JSON::Util::URI.parse memory leak [\#329](https://github.com/voxpupuli/json-schema/issues/329) - additionalProperties is tested and implemented incorrectly [\#321](https://github.com/voxpupuli/json-schema/issues/321) **Merged pull requests:** - Updated ruby versions for travis [\#372](https://github.com/voxpupuli/json-schema/pull/372) ([iainbeeston](https://github.com/iainbeeston)) - Load local copy of draft schemas [\#362](https://github.com/voxpupuli/json-schema/pull/362) ([iainbeeston](https://github.com/iainbeeston)) - Made sure clear\_cache also clears the cache of parsed uris [\#361](https://github.com/voxpupuli/json-schema/pull/361) ([iainbeeston](https://github.com/iainbeeston)) - Simplified `#validator_for` methods [\#346](https://github.com/voxpupuli/json-schema/pull/346) ([iainbeeston](https://github.com/iainbeeston)) - Moved Validator\#absolutized\_uri and RefAttribute's ref parsing into the URI module [\#345](https://github.com/voxpupuli/json-schema/pull/345) ([iainbeeston](https://github.com/iainbeeston)) - Deprecated `JSON::Validator#validate2` [\#336](https://github.com/voxpupuli/json-schema/pull/336) ([iainbeeston](https://github.com/iainbeeston)) - Deprecated \#extend\_schema\_definition [\#335](https://github.com/voxpupuli/json-schema/pull/335) ([iainbeeston](https://github.com/iainbeeston)) - Use self or self.class rather than fully qualified class names [\#333](https://github.com/voxpupuli/json-schema/pull/333) ([iainbeeston](https://github.com/iainbeeston)) - Stopped the additional properties test from using class\_eval [\#332](https://github.com/voxpupuli/json-schema/pull/332) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.7.0](https://github.com/voxpupuli/json-schema/tree/v2.7.0) (2016-09-29) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.6.2...v2.7.0) **Closed issues:** - Test failure due to update in JSON-Schema-Test-Suite [\#357](https://github.com/voxpupuli/json-schema/issues/357) - addressable conflict [\#355](https://github.com/voxpupuli/json-schema/issues/355) - String "uri" format validation doesn't work [\#353](https://github.com/voxpupuli/json-schema/issues/353) - How I can set string format by uri or email? [\#351](https://github.com/voxpupuli/json-schema/issues/351) - Whitelisting properties [\#331](https://github.com/voxpupuli/json-schema/issues/331) - How to build a complex schema when using with Rails [\#328](https://github.com/voxpupuli/json-schema/issues/328) - Issues validating objects with oneOf [\#327](https://github.com/voxpupuli/json-schema/issues/327) - Trouble with Oj parser on parse error [\#305](https://github.com/voxpupuli/json-schema/issues/305) - tests failing with ruby 2.2 uninitialized constant JSONSchemaDraft1Test::ArrayValidation \(NameError\) [\#262](https://github.com/voxpupuli/json-schema/issues/262) **Merged pull requests:** - Made it possible to have a property named "$ref" [\#360](https://github.com/voxpupuli/json-schema/pull/360) ([iainbeeston](https://github.com/iainbeeston)) - Use latest json-schema draft in tests by default [\#359](https://github.com/voxpupuli/json-schema/pull/359) ([iainbeeston](https://github.com/iainbeeston)) - Restricted the ruby 1.9 build to json \< 2 [\#350](https://github.com/voxpupuli/json-schema/pull/350) ([iainbeeston](https://github.com/iainbeeston)) - Item partial tuples [\#348](https://github.com/voxpupuli/json-schema/pull/348) ([jlfaber](https://github.com/jlfaber)) - Removed the ruby 1.8 build from travis [\#340](https://github.com/voxpupuli/json-schema/pull/340) ([iainbeeston](https://github.com/iainbeeston)) - Made sure all validate methods go through the same call chain [\#338](https://github.com/voxpupuli/json-schema/pull/338) ([iainbeeston](https://github.com/iainbeeston)) - Fixed issues with caching [\#334](https://github.com/voxpupuli/json-schema/pull/334) ([iainbeeston](https://github.com/iainbeeston)) - Allow addressable 2.4+ to work with json-schema [\#312](https://github.com/voxpupuli/json-schema/pull/312) ([iainbeeston](https://github.com/iainbeeston)) - Tidy up tests [\#290](https://github.com/voxpupuli/json-schema/pull/290) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.6.2](https://github.com/voxpupuli/json-schema/tree/v2.6.2) (2016-05-13) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.6.1...v2.6.2) **Closed issues:** - "required" array in sub schema not being checked [\#325](https://github.com/voxpupuli/json-schema/issues/325) - optional attributes are not being parsed as optional [\#324](https://github.com/voxpupuli/json-schema/issues/324) - JSON pointers are broken when they contain a `:` [\#319](https://github.com/voxpupuli/json-schema/issues/319) - MultiJSON receives filepath instead of its content [\#318](https://github.com/voxpupuli/json-schema/issues/318) - Chef DK installs addressable 2.4.0 which conflicts with the requirement for 2.3.8 for json-schema [\#317](https://github.com/voxpupuli/json-schema/issues/317) - Empty array \(incorrectly?\) triggering ValidationError [\#311](https://github.com/voxpupuli/json-schema/issues/311) **Merged pull requests:** - Made it possible to have refs that include URI-special characters [\#322](https://github.com/voxpupuli/json-schema/pull/322) ([iainbeeston](https://github.com/iainbeeston)) - Reformatted the examples to make them easier to read [\#316](https://github.com/voxpupuli/json-schema/pull/316) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.6.1](https://github.com/voxpupuli/json-schema/tree/v2.6.1) (2016-02-26) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.6.0...v2.6.1) **Closed issues:** - uninitialized constant JSON::Validator::SchemaParseError [\#307](https://github.com/voxpupuli/json-schema/issues/307) - How can I perform more complex validations [\#306](https://github.com/voxpupuli/json-schema/issues/306) - `fully_validate` // `anyOf`, `typeOf`, `allOf` don't raise validation errors when using `record_errors: true` [\#300](https://github.com/voxpupuli/json-schema/issues/300) - Feature Request: provide ref-like path for allOf/oneOf matches if validation fails. [\#298](https://github.com/voxpupuli/json-schema/issues/298) - NameError: uninitialized constant JSON::Validator::SchemaParseError [\#292](https://github.com/voxpupuli/json-schema/issues/292) - oneOf and patternProperties validates incorrectly [\#291](https://github.com/voxpupuli/json-schema/issues/291) - Validate a schema [\#287](https://github.com/voxpupuli/json-schema/issues/287) **Merged pull requests:** - Update README.md [\#308](https://github.com/voxpupuli/json-schema/pull/308) ([cassiascheffer](https://github.com/cassiascheffer)) - Convert readme to markdown [\#302](https://github.com/voxpupuli/json-schema/pull/302) ([lencioni](https://github.com/lencioni)) - Made sure we include the module name for SchemaParseErrors [\#293](https://github.com/voxpupuli/json-schema/pull/293) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.6.0](https://github.com/voxpupuli/json-schema/tree/v2.6.0) (2016-01-08) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.5.2...v2.6.0) **Closed issues:** - How to validate data with only part of my schema [\#288](https://github.com/voxpupuli/json-schema/issues/288) - Addressable::Uri does not raise error on invalid strings [\#282](https://github.com/voxpupuli/json-schema/issues/282) - typeOf array doesn't validate references [\#281](https://github.com/voxpupuli/json-schema/issues/281) - register\_format\_validator doesn't add format to @@default\_validator [\#276](https://github.com/voxpupuli/json-schema/issues/276) - JSON API 1.0 Support [\#272](https://github.com/voxpupuli/json-schema/issues/272) **Merged pull requests:** - Remove ruby warnings [\#286](https://github.com/voxpupuli/json-schema/pull/286) ([teoljungberg](https://github.com/teoljungberg)) - Redux: speed up JSON::Validator.validate [\#285](https://github.com/voxpupuli/json-schema/pull/285) ([iainbeeston](https://github.com/iainbeeston)) - Test all versions in test\_custom\_format [\#278](https://github.com/voxpupuli/json-schema/pull/278) ([jpmckinney](https://github.com/jpmckinney)) - Update README.textile to fix schema validation example [\#271](https://github.com/voxpupuli/json-schema/pull/271) ([mkonecny](https://github.com/mkonecny)) - Only rescue errors explicitly [\#239](https://github.com/voxpupuli/json-schema/pull/239) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.5.2](https://github.com/voxpupuli/json-schema/tree/v2.5.2) (2015-11-24) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.5.1...v2.5.2) **Closed issues:** - Properties as Property not working [\#273](https://github.com/voxpupuli/json-schema/issues/273) - Schema nesting with id key is not validating as expected [\#270](https://github.com/voxpupuli/json-schema/issues/270) - Does not validate email correctly... [\#269](https://github.com/voxpupuli/json-schema/issues/269) - No implicit conversion of integer [\#259](https://github.com/voxpupuli/json-schema/issues/259) - No implicit conversion of integer to string with links [\#258](https://github.com/voxpupuli/json-schema/issues/258) - Automatically parse number values [\#257](https://github.com/voxpupuli/json-schema/issues/257) - Does not fail for type number when the data is string [\#251](https://github.com/voxpupuli/json-schema/issues/251) - Prepare release of 2.5.1 [\#228](https://github.com/voxpupuli/json-schema/issues/228) - Unable to set clear\_cache option [\#225](https://github.com/voxpupuli/json-schema/issues/225) - Incorrect exception message in 2.5.0 [\#220](https://github.com/voxpupuli/json-schema/issues/220) - Trouble with forbidden additionalProperties and one/any/allOf? [\#161](https://github.com/voxpupuli/json-schema/issues/161) **Merged pull requests:** - register\_format\_validator on default\_validator [\#277](https://github.com/voxpupuli/json-schema/pull/277) ([jpmckinney](https://github.com/jpmckinney)) - Explicitly notes :strict overrides any required properties set in schema [\#252](https://github.com/voxpupuli/json-schema/pull/252) ([KTKate](https://github.com/KTKate)) - Use old hash syntax in tests [\#240](https://github.com/voxpupuli/json-schema/pull/240) ([iainbeeston](https://github.com/iainbeeston)) - Allow boolean false as a default property. [\#238](https://github.com/voxpupuli/json-schema/pull/238) ([chrisandreae](https://github.com/chrisandreae)) - Removed test files from gemspec [\#237](https://github.com/voxpupuli/json-schema/pull/237) ([iainbeeston](https://github.com/iainbeeston)) - Expose clear\_cache option [\#235](https://github.com/voxpupuli/json-schema/pull/235) ([danieldraper](https://github.com/danieldraper)) - Enabled warnings when running tests [\#231](https://github.com/voxpupuli/json-schema/pull/231) ([iainbeeston](https://github.com/iainbeeston)) ## [v2.5.1](https://github.com/voxpupuli/json-schema/tree/v2.5.1) (2015-02-23) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/v2.5.0...v2.5.1) **Closed issues:** - Passing in a fragment with an even number of tokens can lead to undefined method `validate' for \#\ [\#265](https://github.com/voxpupuli/json-schema/issues/265) - Absoluteness correction [\#233](https://github.com/voxpupuli/json-schema/issues/233) - Consider releasing 2.5.1 [\#227](https://github.com/voxpupuli/json-schema/issues/227) **Merged pull requests:** - Ignore fragments in schema caching. Fixes \#233 [\#234](https://github.com/voxpupuli/json-schema/pull/234) ([jphastings](https://github.com/jphastings)) - Only add violating properties to error message for strict validation [\#230](https://github.com/voxpupuli/json-schema/pull/230) ([RST-J](https://github.com/RST-J)) - Show sub-errors for oneOf [\#216](https://github.com/voxpupuli/json-schema/pull/216) ([isage](https://github.com/isage)) - Update README - latest version is currently 2.5.0 [\#215](https://github.com/voxpupuli/json-schema/pull/215) ([take](https://github.com/take)) - End single quote in validation error [\#213](https://github.com/voxpupuli/json-schema/pull/213) ([olleolleolle](https://github.com/olleolleolle)) - add description for nested types array and object [\#212](https://github.com/voxpupuli/json-schema/pull/212) ([brancz](https://github.com/brancz)) - Updated to addressable 2.3.7 [\#226](https://github.com/voxpupuli/json-schema/pull/226) ([iainbeeston](https://github.com/iainbeeston)) - Made sure we really do update the common test suite before test runs [\#224](https://github.com/voxpupuli/json-schema/pull/224) ([iainbeeston](https://github.com/iainbeeston)) - Added Ruby 2.2 to the build matrix [\#223](https://github.com/voxpupuli/json-schema/pull/223) ([iainbeeston](https://github.com/iainbeeston)) - Renamed variable in oneOf to avoid name clash [\#221](https://github.com/voxpupuli/json-schema/pull/221) ([iainbeeston](https://github.com/iainbeeston)) - Issue with Fixnum and Float in enum [\#219](https://github.com/voxpupuli/json-schema/pull/219) ([RST-J](https://github.com/RST-J)) ## [v2.5.0](https://github.com/voxpupuli/json-schema/tree/v2.5.0) (2014-12-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.4.1...v2.5.0) **Closed issues:** - additionalProperties and $ref are not working together [\#185](https://github.com/voxpupuli/json-schema/issues/185) - Dependencies [\#179](https://github.com/voxpupuli/json-schema/issues/179) - Use Addressable for handling URIs? [\#173](https://github.com/voxpupuli/json-schema/issues/173) - Full support for the common test suite [\#163](https://github.com/voxpupuli/json-schema/issues/163) - Remove yajl-Ruby support in favour of multi\_json [\#162](https://github.com/voxpupuli/json-schema/issues/162) - Drop support for email and hostname formats [\#159](https://github.com/voxpupuli/json-schema/issues/159) - format: date-time validator isn't leap-second compliant [\#123](https://github.com/voxpupuli/json-schema/issues/123) - Symbol keys not handled in combination with additionalProperties [\#108](https://github.com/voxpupuli/json-schema/issues/108) - When extending a schema in folder names with spaces [\#100](https://github.com/voxpupuli/json-schema/issues/100) - Enhancing schema draft [\#99](https://github.com/voxpupuli/json-schema/issues/99) - Doesn't work in JRuby \(1.7.10 or 1.7.6\) with --1.8 [\#95](https://github.com/voxpupuli/json-schema/issues/95) - Support for string "format" attribute [\#79](https://github.com/voxpupuli/json-schema/issues/79) - Provide secure way of testing [\#77](https://github.com/voxpupuli/json-schema/issues/77) - Breaks with multi\_json 1.7.9 \(works with 1.7.7\) [\#73](https://github.com/voxpupuli/json-schema/issues/73) - additionalProperties and extends don't work together [\#31](https://github.com/voxpupuli/json-schema/issues/31) - Next minor release \(2.5.0\) [\#202](https://github.com/voxpupuli/json-schema/issues/202) **Merged pull requests:** - Added bundler gem management rake tasks [\#211](https://github.com/voxpupuli/json-schema/pull/211) ([iainbeeston](https://github.com/iainbeeston)) - Refactored parser error code [\#210](https://github.com/voxpupuli/json-schema/pull/210) ([iainbeeston](https://github.com/iainbeeston)) - WebMock is on globally now; no need to disable it [\#208](https://github.com/voxpupuli/json-schema/pull/208) ([pd](https://github.com/pd)) - Addressable spring clean [\#199](https://github.com/voxpupuli/json-schema/pull/199) ([iainbeeston](https://github.com/iainbeeston)) - Tidied the common test suite tests [\#197](https://github.com/voxpupuli/json-schema/pull/197) ([iainbeeston](https://github.com/iainbeeston)) - Remove "no dependencies" claim from README [\#194](https://github.com/voxpupuli/json-schema/pull/194) ([pd](https://github.com/pd)) - Remove unused Schema\#base\_uri method [\#193](https://github.com/voxpupuli/json-schema/pull/193) ([pd](https://github.com/pd)) - Updated the common test suite [\#191](https://github.com/voxpupuli/json-schema/pull/191) ([iainbeeston](https://github.com/iainbeeston)) - Use unescape for paths before reading files [\#188](https://github.com/voxpupuli/json-schema/pull/188) ([RST-J](https://github.com/RST-J)) - Use the new build env on Travis [\#187](https://github.com/voxpupuli/json-schema/pull/187) ([joshk](https://github.com/joshk)) - `oneOf` and `anyOf` errors where default values are present [\#181](https://github.com/voxpupuli/json-schema/pull/181) ([tonymarklove](https://github.com/tonymarklove)) - Only stringify schema once [\#180](https://github.com/voxpupuli/json-schema/pull/180) ([treppo](https://github.com/treppo)) - Refactor ref schema URI construction. [\#177](https://github.com/voxpupuli/json-schema/pull/177) ([gabrielg](https://github.com/gabrielg)) - Use RFC 2606 reserved invalid DNS name in tests. [\#176](https://github.com/voxpupuli/json-schema/pull/176) ([gabrielg](https://github.com/gabrielg)) - Use Addressable gem to handle URIs [\#174](https://github.com/voxpupuli/json-schema/pull/174) ([RST-J](https://github.com/RST-J)) - General cleanup, mostly focused on attributes/\* [\#172](https://github.com/voxpupuli/json-schema/pull/172) ([pd](https://github.com/pd)) - Extend common-test-suite to ignore individual test cases [\#171](https://github.com/voxpupuli/json-schema/pull/171) ([mpalmer](https://github.com/mpalmer)) - Added some tests around file uris [\#169](https://github.com/voxpupuli/json-schema/pull/169) ([iainbeeston](https://github.com/iainbeeston)) - Add some test helpers for common patterns [\#168](https://github.com/voxpupuli/json-schema/pull/168) ([pd](https://github.com/pd)) - Removed multijson license [\#167](https://github.com/voxpupuli/json-schema/pull/167) ([iainbeeston](https://github.com/iainbeeston)) - Add mailing list and IRC channel [\#166](https://github.com/voxpupuli/json-schema/pull/166) ([hoxworth](https://github.com/hoxworth)) - Fix draft3 `disallow` validation [\#165](https://github.com/voxpupuli/json-schema/pull/165) ([pd](https://github.com/pd)) - Enable refremote specs [\#164](https://github.com/voxpupuli/json-schema/pull/164) ([pd](https://github.com/pd)) - Fix for relative ref with fragment identifier on Windows [\#109](https://github.com/voxpupuli/json-schema/pull/109) ([jlblcc](https://github.com/jlblcc)) - Any ref issue [\#200](https://github.com/voxpupuli/json-schema/pull/200) ([RST-J](https://github.com/RST-J)) - Fix test runs for optional dependencies [\#196](https://github.com/voxpupuli/json-schema/pull/196) ([iainbeeston](https://github.com/iainbeeston)) - JSON::Schema::Reader [\#175](https://github.com/voxpupuli/json-schema/pull/175) ([pd](https://github.com/pd)) ## [2.4.1](https://github.com/voxpupuli/json-schema/tree/2.4.1) (2014-10-28) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.4.0...2.4.1) **Merged pull requests:** - Replaced \#add\_indifferent\_access with \#stringify [\#142](https://github.com/voxpupuli/json-schema/pull/142) ([iainbeeston](https://github.com/iainbeeston)) ## [2.4.0](https://github.com/voxpupuli/json-schema/tree/2.4.0) (2014-10-28) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.3.0...2.4.0) **Fixed bugs:** - Bug in IPV6 format validation [\#133](https://github.com/voxpupuli/json-schema/issues/133) **Closed issues:** - Path issue when validating draft-04 schema [\#160](https://github.com/voxpupuli/json-schema/issues/160) - Schema validation is broken in master [\#135](https://github.com/voxpupuli/json-schema/issues/135) - Dependencies don't seem to work correctly [\#117](https://github.com/voxpupuli/json-schema/issues/117) - Use common test suite? [\#113](https://github.com/voxpupuli/json-schema/issues/113) - "Fix symbol keys in data" breaks working implementations [\#96](https://github.com/voxpupuli/json-schema/issues/96) **Merged pull requests:** - Add yajl, multi\_json and uuidtools to travis [\#157](https://github.com/voxpupuli/json-schema/pull/157) ([iainbeeston](https://github.com/iainbeeston)) - Store static regexps in constants for re-use [\#156](https://github.com/voxpupuli/json-schema/pull/156) ([pd](https://github.com/pd)) - Fix metaschema access [\#155](https://github.com/voxpupuli/json-schema/pull/155) ([pd](https://github.com/pd)) - Add ruby 1.8 to travis [\#154](https://github.com/voxpupuli/json-schema/pull/154) ([iainbeeston](https://github.com/iainbeeston)) - Enable draft4/dependencies test [\#153](https://github.com/voxpupuli/json-schema/pull/153) ([pd](https://github.com/pd)) - Add 1.8.7 minimum ruby version to the spec [\#149](https://github.com/voxpupuli/json-schema/pull/149) ([hoxworth](https://github.com/hoxworth)) - Validator tidy [\#147](https://github.com/voxpupuli/json-schema/pull/147) ([iainbeeston](https://github.com/iainbeeston)) - Unescape ref fragment pointers [\#146](https://github.com/voxpupuli/json-schema/pull/146) ([pd](https://github.com/pd)) - Fix schema dep v4 [\#145](https://github.com/voxpupuli/json-schema/pull/145) ([RST-J](https://github.com/RST-J)) - Update descr [\#144](https://github.com/voxpupuli/json-schema/pull/144) ([RST-J](https://github.com/RST-J)) - Use IPAddr class to validate ip formats [\#143](https://github.com/voxpupuli/json-schema/pull/143) ([RST-J](https://github.com/RST-J)) - Added codeclimate badge to readme [\#141](https://github.com/voxpupuli/json-schema/pull/141) ([iainbeeston](https://github.com/iainbeeston)) - Make intra-doc refs work when validating with :fragment [\#127](https://github.com/voxpupuli/json-schema/pull/127) ([mpalmer](https://github.com/mpalmer)) - Hyper validation [\#125](https://github.com/voxpupuli/json-schema/pull/125) ([mpalmer](https://github.com/mpalmer)) - Parse dates using ruby's own date parsing - not regular expressions [\#118](https://github.com/voxpupuli/json-schema/pull/118) ([iainbeeston](https://github.com/iainbeeston)) ## [2.3.0](https://github.com/voxpupuli/json-schema/tree/2.3.0) (2014-10-26) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.2.4...2.3.0) **Fixed bugs:** - Possible bug: nil items in Array properties are stripped before MinItems validation [\#129](https://github.com/voxpupuli/json-schema/issues/129) - some questions about addtionalproperties [\#112](https://github.com/voxpupuli/json-schema/issues/112) **Closed issues:** - Possible bug: wrong expectation of required object property [\#139](https://github.com/voxpupuli/json-schema/issues/139) - Array Validates Against Schema When It Shouldn't [\#137](https://github.com/voxpupuli/json-schema/issues/137) - Registration of custom format validators [\#128](https://github.com/voxpupuli/json-schema/issues/128) - Invalid schema not reported using fully\_validate with a oneOf attribute [\#116](https://github.com/voxpupuli/json-schema/issues/116) - Errors for required properties do not contain the fragment correctly. [\#115](https://github.com/voxpupuli/json-schema/issues/115) - Use of String\#each breaks Ruby 1.9 [\#78](https://github.com/voxpupuli/json-schema/issues/78) **Merged pull requests:** - Do not compact before checking minItems [\#140](https://github.com/voxpupuli/json-schema/pull/140) ([pd](https://github.com/pd)) - Made validation sub errors indicate where they come from [\#138](https://github.com/voxpupuli/json-schema/pull/138) ([iainbeeston](https://github.com/iainbeeston)) - Add support for `"required": false` while using draft3 with strict mode [\#134](https://github.com/voxpupuli/json-schema/pull/134) ([bkirz](https://github.com/bkirz)) - Custom formats [\#132](https://github.com/voxpupuli/json-schema/pull/132) ([RST-J](https://github.com/RST-J)) - Extract formats into separate classes [\#131](https://github.com/voxpupuli/json-schema/pull/131) ([RST-J](https://github.com/RST-J)) - Refactor classes and validator accessor methods [\#130](https://github.com/voxpupuli/json-schema/pull/130) ([iainbeeston](https://github.com/iainbeeston)) - Another allOf ref test, and rename class [\#126](https://github.com/voxpupuli/json-schema/pull/126) ([mpalmer](https://github.com/mpalmer)) - Fix bad ref test for proxy support [\#124](https://github.com/voxpupuli/json-schema/pull/124) ([mpalmer](https://github.com/mpalmer)) - Run json-schema.org's common test suite [\#122](https://github.com/voxpupuli/json-schema/pull/122) ([mpalmer](https://github.com/mpalmer)) - Stopped draft3 from registering itself as the default validator [\#121](https://github.com/voxpupuli/json-schema/pull/121) ([iainbeeston](https://github.com/iainbeeston)) - Added ruby 2.0, rubinius and jruby to travis build [\#119](https://github.com/voxpupuli/json-schema/pull/119) ([iainbeeston](https://github.com/iainbeeston)) - Handle non-latin uris [\#114](https://github.com/voxpupuli/json-schema/pull/114) ([iainbeeston](https://github.com/iainbeeston)) - Remove deprecated :rubygems source from Gemfile [\#111](https://github.com/voxpupuli/json-schema/pull/111) ([jamiecobbett](https://github.com/jamiecobbett)) ## [2.2.4](https://github.com/voxpupuli/json-schema/tree/2.2.4) (2014-07-19) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.2.3...2.2.4) **Closed issues:** - Not correctly validating: "The property did not match the following type: string in schema" [\#101](https://github.com/voxpupuli/json-schema/issues/101) - Validator return error when data is an array with hash with symbolic keys [\#94](https://github.com/voxpupuli/json-schema/issues/94) **Merged pull requests:** - Fix `list:true` when referencing a cached schema [\#107](https://github.com/voxpupuli/json-schema/pull/107) ([pd](https://github.com/pd)) - Setup travis [\#106](https://github.com/voxpupuli/json-schema/pull/106) ([apsoto](https://github.com/apsoto)) ## [2.2.3](https://github.com/voxpupuli/json-schema/tree/2.2.3) (2014-07-16) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/1.2.1...2.2.3) **Closed issues:** - Symbol keys are not supported in objects within arrays [\#104](https://github.com/voxpupuli/json-schema/issues/104) **Merged pull requests:** - Make hashes in arrays indifferent to string/symbol keys [\#105](https://github.com/voxpupuli/json-schema/pull/105) ([jennyd](https://github.com/jennyd)) - Load files from namespaced location to avoid conflicts [\#98](https://github.com/voxpupuli/json-schema/pull/98) ([kjg](https://github.com/kjg)) ## [1.2.1](https://github.com/voxpupuli/json-schema/tree/1.2.1) (2014-01-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.2.1...1.2.1) ## [2.2.1](https://github.com/voxpupuli/json-schema/tree/2.2.1) (2014-01-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.2.0...2.2.1) ## [2.2.0](https://github.com/voxpupuli/json-schema/tree/2.2.0) (2014-01-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/1.2.0...2.2.0) ## [1.2.0](https://github.com/voxpupuli/json-schema/tree/1.2.0) (2014-01-15) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.8...1.2.0) **Closed issues:** - No error when schema not found [\#87](https://github.com/voxpupuli/json-schema/issues/87) - Schema validation should not clear cache [\#82](https://github.com/voxpupuli/json-schema/issues/82) ## [2.1.8](https://github.com/voxpupuli/json-schema/tree/2.1.8) (2014-01-04) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.7...2.1.8) **Closed issues:** - Enum conversion to a Hash breaks Schema Validation [\#93](https://github.com/voxpupuli/json-schema/issues/93) **Merged pull requests:** - Fix logic error in format validation [\#80](https://github.com/voxpupuli/json-schema/pull/80) ([jpmckinney](https://github.com/jpmckinney)) ## [2.1.7](https://github.com/voxpupuli/json-schema/tree/2.1.7) (2014-01-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.6...2.1.7) **Closed issues:** - Validation still requires data hash keys to be strings. Contrary to most recent version's stated purpose. [\#74](https://github.com/voxpupuli/json-schema/issues/74) ## [2.1.6](https://github.com/voxpupuli/json-schema/tree/2.1.6) (2014-01-01) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.5...2.1.6) **Closed issues:** - Validator takes too long to validate JSON. [\#89](https://github.com/voxpupuli/json-schema/issues/89) - JSON::Validator.fully\_validate returns error for valid schema with "not" keyword in it [\#84](https://github.com/voxpupuli/json-schema/issues/84) - JSON::Validator modifies schema object [\#83](https://github.com/voxpupuli/json-schema/issues/83) - 2.1.2 broke 1.8.7 compatibility [\#62](https://github.com/voxpupuli/json-schema/issues/62) ## [2.1.5](https://github.com/voxpupuli/json-schema/tree/2.1.5) (2014-01-01) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.4...2.1.5) **Closed issues:** - Can you push up the tags? [\#91](https://github.com/voxpupuli/json-schema/issues/91) - JSON::Validator.default\_validator is being set to draft-03 by default [\#76](https://github.com/voxpupuli/json-schema/issues/76) - Can't validate with fragment [\#64](https://github.com/voxpupuli/json-schema/issues/64) - Schema-wide "required" doesn't work [\#61](https://github.com/voxpupuli/json-schema/issues/61) ## [2.1.4](https://github.com/voxpupuli/json-schema/tree/2.1.4) (2013-12-31) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.3...2.1.4) **Closed issues:** - Fat arrow vs colon [\#88](https://github.com/voxpupuli/json-schema/issues/88) - allOf and $ref not working? [\#86](https://github.com/voxpupuli/json-schema/issues/86) - Returns "valid" when schema is invalid [\#81](https://github.com/voxpupuli/json-schema/issues/81) - How to validate schema only? [\#71](https://github.com/voxpupuli/json-schema/issues/71) - $ref in anyOf, allOf, etc don't work [\#66](https://github.com/voxpupuli/json-schema/issues/66) - Problem with $ref to validate array property [\#63](https://github.com/voxpupuli/json-schema/issues/63) - License missing from gemspec [\#60](https://github.com/voxpupuli/json-schema/issues/60) **Merged pull requests:** - Fix issue 86 [\#92](https://github.com/voxpupuli/json-schema/pull/92) ([sebbacon](https://github.com/sebbacon)) - Updated date-time regex to accept zero or one of : in the timezone designator [\#85](https://github.com/voxpupuli/json-schema/pull/85) ([jwarykowski](https://github.com/jwarykowski)) - Fixed fragment resolution. Issue \#64 [\#75](https://github.com/voxpupuli/json-schema/pull/75) ([arcticlcc](https://github.com/arcticlcc)) - Dont break file scheme with unc on windows [\#72](https://github.com/voxpupuli/json-schema/pull/72) ([kylog](https://github.com/kylog)) - Fix one of logic [\#70](https://github.com/voxpupuli/json-schema/pull/70) ([apsoto](https://github.com/apsoto)) - Add Gemfile and ignore Gemfile.lock. [\#68](https://github.com/voxpupuli/json-schema/pull/68) ([ryotarai](https://github.com/ryotarai)) ## [2.1.3](https://github.com/voxpupuli/json-schema/tree/2.1.3) (2013-08-02) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.2...2.1.3) **Closed issues:** - Fail on ruby 1.9.3, jruby 1.6.8 --1.9 [\#45](https://github.com/voxpupuli/json-schema/issues/45) **Merged pull requests:** - Fix Issue \#66 [\#67](https://github.com/voxpupuli/json-schema/pull/67) ([apsoto](https://github.com/apsoto)) ## [2.1.2](https://github.com/voxpupuli/json-schema/tree/2.1.2) (2013-07-19) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.1...2.1.2) **Closed issues:** - validate\_schema does not use value of $schema [\#59](https://github.com/voxpupuli/json-schema/issues/59) ## [2.1.1](https://github.com/voxpupuli/json-schema/tree/2.1.1) (2013-07-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.1.0...2.1.1) **Closed issues:** - Validate against a schema fragment. [\#56](https://github.com/voxpupuli/json-schema/issues/56) - 1.0.9 has ruby 1.9.x dependency; breaks patch compatibility [\#44](https://github.com/voxpupuli/json-schema/issues/44) ## [2.1.0](https://github.com/voxpupuli/json-schema/tree/2.1.0) (2013-07-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.0.4...2.1.0) **Closed issues:** - json-schema 2.0.1 broke schema validation [\#58](https://github.com/voxpupuli/json-schema/issues/58) - maxItems is not working [\#54](https://github.com/voxpupuli/json-schema/issues/54) **Merged pull requests:** - Add failing test demonstrating failure of complex union type. [\#52](https://github.com/voxpupuli/json-schema/pull/52) ([myronmarston](https://github.com/myronmarston)) ## [2.0.4](https://github.com/voxpupuli/json-schema/tree/2.0.4) (2013-07-01) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.0.3...2.0.4) **Closed issues:** - ISO 8601 date-times do not include UTC offset [\#42](https://github.com/voxpupuli/json-schema/issues/42) **Merged pull requests:** - Show schema type in error message instead of ruby class [\#50](https://github.com/voxpupuli/json-schema/pull/50) ([jvatic](https://github.com/jvatic)) ## [2.0.3](https://github.com/voxpupuli/json-schema/tree/2.0.3) (2013-06-26) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.0.2...2.0.3) **Merged pull requests:** - Fix date-time format. [\#43](https://github.com/voxpupuli/json-schema/pull/43) ([chris-baynes](https://github.com/chris-baynes)) ## [2.0.2](https://github.com/voxpupuli/json-schema/tree/2.0.2) (2013-06-26) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.0.1...2.0.2) **Closed issues:** - Unable to Validate v4 Schema File [\#57](https://github.com/voxpupuli/json-schema/issues/57) **Merged pull requests:** - maxitems error message correction [\#55](https://github.com/voxpupuli/json-schema/pull/55) ([lpavan](https://github.com/lpavan)) - Extends support array of objects too [\#53](https://github.com/voxpupuli/json-schema/pull/53) ([rogerleite](https://github.com/rogerleite)) ## [2.0.1](https://github.com/voxpupuli/json-schema/tree/2.0.1) (2013-06-25) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/2.0.0...2.0.1) **Closed issues:** - Support draft v4 [\#51](https://github.com/voxpupuli/json-schema/issues/51) ## [2.0.0](https://github.com/voxpupuli/json-schema/tree/2.0.0) (2013-06-23) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/1.0.4...2.0.0) **Closed issues:** - json\_schema with old multi\_json in Rails context [\#39](https://github.com/voxpupuli/json-schema/issues/39) - Doesn't work with 1.9 stdlib JSON [\#33](https://github.com/voxpupuli/json-schema/issues/33) - Validation not working on nested properties [\#30](https://github.com/voxpupuli/json-schema/issues/30) - Add in a validation error structure [\#29](https://github.com/voxpupuli/json-schema/issues/29) - union types with schemas don't work with :record\_errors =\> true [\#27](https://github.com/voxpupuli/json-schema/issues/27) - Validator is not thread safe [\#24](https://github.com/voxpupuli/json-schema/issues/24) **Merged pull requests:** - More descriptive error message for PatternAttribute [\#49](https://github.com/voxpupuli/json-schema/pull/49) ([quoideneuf](https://github.com/quoideneuf)) - Support \(optional\) adding of default values to input data while validating [\#48](https://github.com/voxpupuli/json-schema/pull/48) ([goodsimon](https://github.com/goodsimon)) - Restore 1.8.7 compatibility. [\#46](https://github.com/voxpupuli/json-schema/pull/46) ([myronmarston](https://github.com/myronmarston)) - Extends and additional properties take 2 [\#41](https://github.com/voxpupuli/json-schema/pull/41) ([japgolly](https://github.com/japgolly)) - Fix Issue with MultiJson Feature Detection [\#40](https://github.com/voxpupuli/json-schema/pull/40) ([tylerhunt](https://github.com/tylerhunt)) - Extract type validation into a helper method. [\#38](https://github.com/voxpupuli/json-schema/pull/38) ([myronmarston](https://github.com/myronmarston)) - date-time format and fractional seconds part [\#36](https://github.com/voxpupuli/json-schema/pull/36) ([ILikePies](https://github.com/ILikePies)) - Play nicely with new and old versions of MultiJson [\#35](https://github.com/voxpupuli/json-schema/pull/35) ([japgolly](https://github.com/japgolly)) - Validation fails if root data object is a string [\#26](https://github.com/voxpupuli/json-schema/pull/26) ([vapir](https://github.com/vapir)) ## [1.0.4](https://github.com/voxpupuli/json-schema/tree/1.0.4) (2012-02-14) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/1.0.0...1.0.4) **Closed issues:** - Extending a schema doesn't allow overrides [\#22](https://github.com/voxpupuli/json-schema/issues/22) **Merged pull requests:** - Multijson and schema validation [\#28](https://github.com/voxpupuli/json-schema/pull/28) ([myronmarston](https://github.com/myronmarston)) - Json::Schema::\*Error classes should inherit from StandardError instead of Exception. [\#25](https://github.com/voxpupuli/json-schema/pull/25) ([tommay](https://github.com/tommay)) - More descriptive error messages [\#23](https://github.com/voxpupuli/json-schema/pull/23) ([zachmargolis](https://github.com/zachmargolis)) ## [1.0.0](https://github.com/voxpupuli/json-schema/tree/1.0.0) (2012-01-04) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.9.12...1.0.0) ## [0.9.12](https://github.com/voxpupuli/json-schema/tree/0.9.12) (2011-12-14) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.9.3...0.9.12) **Closed issues:** - Validation is slow [\#19](https://github.com/voxpupuli/json-schema/issues/19) - dependency with string value [\#18](https://github.com/voxpupuli/json-schema/issues/18) - minLength for non string type [\#17](https://github.com/voxpupuli/json-schema/issues/17) - Hypermedia schema [\#16](https://github.com/voxpupuli/json-schema/issues/16) - SimpleUUID::UUID conflicts with simple\_uuid gem [\#11](https://github.com/voxpupuli/json-schema/issues/11) - UUID class conflict [\#9](https://github.com/voxpupuli/json-schema/issues/9) **Merged pull requests:** - Fixed Issue \#19 - replace schema.inspect with Yajl::Encoder.encode or Marshal.dump as a fallback [\#20](https://github.com/voxpupuli/json-schema/pull/20) ([kindkid](https://github.com/kindkid)) - Fixes for validate\_schema [\#15](https://github.com/voxpupuli/json-schema/pull/15) ([dekellum](https://github.com/dekellum)) - Fix require of attributes and validators to work in Rubinius [\#14](https://github.com/voxpupuli/json-schema/pull/14) ([IPGlider](https://github.com/IPGlider)) - Gem::Specification::find\_by\_name errors [\#12](https://github.com/voxpupuli/json-schema/pull/12) ([oruen](https://github.com/oruen)) - removed new rubygems deprecation warnings [\#10](https://github.com/voxpupuli/json-schema/pull/10) ([Vasfed](https://github.com/Vasfed)) ## [0.9.3](https://github.com/voxpupuli/json-schema/tree/0.9.3) (2011-04-21) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.9.2...0.9.3) **Closed issues:** - typo in lib/json-schema/validator.rb at line 270 [\#8](https://github.com/voxpupuli/json-schema/issues/8) - Relative URIs are resolved improperly [\#5](https://github.com/voxpupuli/json-schema/issues/5) - 'format' constraint should not be validated for null values [\#4](https://github.com/voxpupuli/json-schema/issues/4) **Merged pull requests:** - removed deprecated option has\_rdoc from gemspec [\#7](https://github.com/voxpupuli/json-schema/pull/7) ([Vasfed](https://github.com/Vasfed)) ## [0.9.2](https://github.com/voxpupuli/json-schema/tree/0.9.2) (2011-03-30) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.9.1...0.9.2) ## [0.9.1](https://github.com/voxpupuli/json-schema/tree/0.9.1) (2011-03-21) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.9.0...0.9.1) **Closed issues:** - Previous draft support [\#2](https://github.com/voxpupuli/json-schema/issues/2) **Merged pull requests:** - Do not add hash items while iterating over them. [\#3](https://github.com/voxpupuli/json-schema/pull/3) ([oruen](https://github.com/oruen)) ## [0.9.0](https://github.com/voxpupuli/json-schema/tree/0.9.0) (2011-03-19) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.2.0...0.9.0) ## [0.2.0](https://github.com/voxpupuli/json-schema/tree/0.2.0) (2011-03-09) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.1.14...0.2.0) ## [0.1.14](https://github.com/voxpupuli/json-schema/tree/0.1.14) (2011-03-09) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.1.10...0.1.14) ## [0.1.10](https://github.com/voxpupuli/json-schema/tree/0.1.10) (2011-01-10) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.1.6...0.1.10) ## [0.1.6](https://github.com/voxpupuli/json-schema/tree/0.1.6) (2010-12-03) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/0.1.2...0.1.6) ## [0.1.2](https://github.com/voxpupuli/json-schema/tree/0.1.2) (2010-11-30) [Full Changelog](https://github.com/voxpupuli/json-schema/compare/d1c7b421bbb04d00b06c49e6ebb5ba773d756b12...0.1.2) \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* voxpupuli-json-schema-9b1349a/CONTRIBUTING.md000066400000000000000000000015761515251074100205730ustar00rootroot00000000000000The 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. voxpupuli-json-schema-9b1349a/CONTRIBUTORS.md000066400000000000000000000015521515251074100206130ustar00rootroot00000000000000CONTRIBUTORS ------------ * 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 voxpupuli-json-schema-9b1349a/Gemfile000066400000000000000000000006351515251074100176300ustar00rootroot00000000000000source 'https://rubygems.org' gemspec gem 'minitest', '>= 5.0', '< 7' gem 'minitest_reporters_github', '~> 1.0', '>= 1.0.1' gem 'multi_json', '~> 1.15' gem 'rake', '~> 13.0' gem 'voxpupuli-rubocop', '~> 5.1.0' if RUBY_VERSION >= '3.2' gem 'webmock', '~> 3.23' group :release, optional: true do gem 'faraday-retry', '~> 2.1', require: false gem 'github_changelog_generator', '~> 1.16.4', require: false end voxpupuli-json-schema-9b1349a/LICENSE.md000066400000000000000000000020651515251074100177400ustar00rootroot00000000000000Copyright (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.voxpupuli-json-schema-9b1349a/README.md000066400000000000000000000405701515251074100176160ustar00rootroot00000000000000# Ruby JSON Schema Validator [![License](https://img.shields.io/github/license/voxpupuli/json-schema.svg)](https://github.com/voxpupuli/json-schema/blob/master/LICENSE.md) [![Test](https://github.com/voxpupuli/json-schema/actions/workflows/test.yml/badge.svg)](https://github.com/voxpupuli/json-schema/actions/workflows/test.yml) [![Release](https://github.com/voxpupuli/json-schema/actions/workflows/release.yml/badge.svg)](https://github.com/voxpupuli/json-schema/actions/workflows/release.yml) [![RubyGem Version](https://img.shields.io/gem/v/json-schema.svg)](https://rubygems.org/gems/json-schema) [![RubyGem Downloads](https://img.shields.io/gem/dt/json-schema.svg)](https://rubygems.org/gems/json-schema) [![Donated by Iain Beeston](https://img.shields.io/badge/donated%20by-Iain%20Beeston-fb7047.svg)](#transfer-notice) This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to [JSON Schema Draft 6](https://tools.ietf.org/html/draft-wright-json-schema-01). Legacy support for [JSON Schema Draft 4](http://tools.ietf.org/html/draft-zyp-json-schema-04), [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) - #voxpupuli on irc.libera.chat 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. Version 3.0.0 Upgrade Notes --------------------------- All individual changes are documented in the CHANGELOG.md. The biggest change is that the new version only supports Ruby 2.5 and newer. Take a look into the gemspec file to see the currently supported Ruby version and also `.github/workflows/test.yml` to see the Ruby versions we test on. Installation ------------ From rubygems.org: ```sh gem install json-schema ``` From the git repo: ```sh gem build json-schema.gemspec gem install json-schema-*.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 considered 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 `:parse_integer` option set to false, the integer value given as string will not be parsed. # # => true JSON::Validator.validate({type: "integer"}, "23") # => false JSON::Validator.validate({type: "integer"}, "23", parse_integer: false) # => true JSON::Validator.validate({type: "string"}, "123", parse_integer: false) # => false JSON::Validator.validate({type: "string"}, "123") # # with the `:json` option, the json must be an unparsed json text (not a hash, a uri or a file path) # # => true JSON::Validator.validate(schema, '{ "a": 1 }', :json => true) # => "no implicit conversion of Hash into String" begin JSON::Validator.validate(schema, { "a" => 1 }, :json => true) rescue TypeError => e e.message end # # with the `:uri` option, the json must be a uri or file path (not a hash or a json text) # File.write("data.json", '{ "a": 1 }') # => true JSON::Validator.validate(schema, "data.json", :uri => true) # => "Can't convert Hash into String." begin JSON::Validator.validate(schema, { "a" => 1 }, :uri => true) rescue TypeError => e e.message end # # with the `:clear_cache` option set to true, the internal cache of schemas is # cleared after validation (otherwise schemas are cached for efficiency) # File.write("schema.json", v2_schema.to_json) # => true JSON::Validator.validate("schema.json", {}) File.write("schema.json", schema.to_json) # => true JSON::Validator.validate("schema.json", {}, :clear_cache => true) # => false JSON::Validator.validate("schema.json", {}) ``` Extending Schemas ----------------- For this example, we are going to extend the [JSON Schema Draft 3](http://tools.ietf.org/html/draft-zyp-json-schema-03) specification by adding a 'bitwise-and' property for validation. ```ruby require "json-schema" class BitwiseAndAttribute < JSON::Schema::Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) if data.is_a?(Integer) && data & current_schema.schema['bitwise-and'].to_i == 0 message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-or']}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end class ExtendedSchema < JSON::Schema::Draft3 def initialize super @attributes["bitwise-and"] = BitwiseAndAttribute @uri = JSON::Util::URI.parse("http://test.com/test.json") @names = ["http://test.com/test.json"] end JSON::Validator.register_validator(self.new) end schema = { "$schema" => "http://test.com/test.json", "properties" => { "a" => { "bitwise-and" => 1 }, "b" => { "type" => "string" } } } data = { "a" => 0 } data = {"a" => 1, "b" => "taco"} JSON::Validator.validate(schema,data) # => true data = {"a" => 1, "b" => 5} JSON::Validator.validate(schema,data) # => false data = {"a" => 0, "b" => "taco"} JSON::Validator.validate(schema,data) # => false ``` Custom format validation ------------------------ The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows registering procs as custom format validators which receive the value to be checked as parameter and must raise a `JSON::Schema::CustomFormatError` to indicate a format violation. The error message will be prepended by the property name, e.g. [The property '#a']() ```ruby require "json-schema" format_proc = -> value { raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" } # register the proc for format 'the-answer' for draft4 schema JSON::Validator.register_format_validator("the-answer", format_proc, ["draft4"]) # omitting the version parameter uses ["draft1", "draft2", "draft3", "draft4"] as default JSON::Validator.register_format_validator("the-answer", format_proc) # deregistering the custom validator # (also ["draft1", "draft2", "draft3", "draft4"] as default version) JSON::Validator.deregister_format_validator('the-answer', ["draft4"]) # shortcut to restore the default formats for validators (same default as before) JSON::Validator.restore_default_formats(["draft4"]) # with the validator registered as above, the following results in # ["The property '#a' must be 42"] as returned errors schema = { "$schema" => "http://json-schema.org/draft-04/schema#", "properties" => { "a" => { "type" => "string", "format" => "the-answer", } } } errors = JSON::Validator.fully_validate(schema, {"a" => "23"}) ``` Validating a JSON Schema ------------------------ To validate that a JSON Schema conforms to the JSON Schema standard, you need to validate your schema against the metaschema for the appropriate JSON Schema Draft. All of the normal validation methods can be used for this. First retrieve the appropriate metaschema from the internal cache (using `JSON::Validator.validator_for_name()` or `JSON::Validator.validator_for_uri()`) and then simply validate your schema against it. ```ruby require "json-schema" schema = { "type" => "object", "properties" => { "a" => {"type" => "integer"} } } metaschema = JSON::Validator.validator_for_name("draft4").metaschema # => true JSON::Validator.validate(metaschema, schema) ``` Controlling Remote Schema Reading --------------------------------- In some cases, you may wish to prevent the JSON Schema library from making HTTP calls or reading local files in order to resolve `$ref` schemas. If you fully control all schemas which should be used by validation, this could be accomplished by registering all referenced schemas with the validator in advance: ```ruby schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema')) JSON::Validator.add_schema(schema) ``` If more extensive control is necessary, the `JSON::Schema::Reader` instance used can be configured in a few ways: ```ruby # Change the default schema reader used JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false) # For this validation call, use a reader which only accepts URIs from my-website.com schema_reader = JSON::Schema::Reader.new( :accept_uri => proc { |uri| uri.host == 'my-website.com' } ) JSON::Validator.validate(some_schema, some_object, :schema_reader => schema_reader) ``` The `JSON::Schema::Reader` interface requires only an object which responds to `read(string)` and returns a `JSON::Schema` instance. See the [API documentation](http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader) for more information. JSON Backends ------------- The JSON Schema library currently supports the `json` and `yajl-ruby` backend JSON parsers. If either of these libraries are installed, they will be automatically loaded and used to parse any JSON strings supplied by the user. If more than one of the supported JSON backends are installed, the `yajl-ruby` parser is used by default. This can be changed by issuing the following before validation: ```ruby JSON::Validator.json_backend = :json ``` Optionally, the JSON Schema library supports using the MultiJSON library for selecting JSON backends. If the MultiJSON library is installed, it will be autoloaded. **Deprecation notice:** MultiJSON support is deprecated and will be removed in a future version. To stop using MultiJSON, add the following to your application's initialization code: ```ruby JSON::Validator.use_multi_json = false ``` 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. # Transfer Notice This plugin was originally authored by [Iain Beeston](https://github.com/iainbeeston). The maintainer preferred that [Vox Pupuli](https://voxpupuli.org/) take ownership of the module for future improvement and maintenance. Existing pull requests and issues were transferred, please fork and continue to contribute [here](https://github.com/voxpupuli/json-schema). # License This gem is licensed under the [MIT license](LICENSE.md). ## Release information To make a new release, please do: * update the version in VERSION.yml * Install gems with `bundle install --with release --path .vendor` * generate the changelog with `bundle exec rake changelog` * Check if the new version matches the closed issues/PRs in the changelog * Create a PR with it * After it got merged, push a tag. GitHub actions will do the actual release to rubygems and GitHub Packages voxpupuli-json-schema-9b1349a/Rakefile000066400000000000000000000035241515251074100200020ustar00rootroot00000000000000require 'rake' require 'rake/testtask' desc 'Updates the json-schema common test suite to the latest version' task :update_common_tests do unless File.read('.git/config').include?('submodule "test/test-suite"') sh 'git submodule init' end puts 'Updating json-schema common test suite...' begin sh 'git submodule update --remote --quiet' rescue StandardError warn 'Failed to update common test suite.' end end desc 'Update meta-schemas to the latest version' task :update_meta_schemas do puts 'Updating meta-schemas...' require 'open-uri' require 'thwait' download_threads = Dir['resources/*.json'].map do |path| schema_uri = File.read(path)[/"\$?id"\s*:\s*"(.*?)"/, 1] Thread.new(schema_uri) do |uri| Thread.current[:uri] = uri begin metaschema = URI(uri).read File.write(path, metaschema) rescue StandardError false end end end ThreadsWait.all_waits(*download_threads) do |t| if t.value puts t[:uri] else warn "Failed to update meta-schema #{t[:uri]}" end end end Rake::TestTask.new do |t| t.libs << '.' t.warning = true t.verbose = true t.test_files = FileList.new('test/*_test.rb') end task update: %i[update_common_tests update_meta_schemas] begin require 'voxpupuli/rubocop/rake' rescue LoadError # the voxpupuli-rubocop gem is optional end task default: :test begin require 'rubygems' require 'github_changelog_generator/task' rescue LoadError else GitHubChangelogGenerator::RakeTask.new :changelog do |config| config.exclude_labels = %w[duplicate question invalid wontfix wont-fix skip-changelog dependencies] config.user = 'voxpupuli' config.project = 'json-schema' gem_version = Gem::Specification.load("#{config.project}.gemspec").version config.future_release = "v#{gem_version}" end end voxpupuli-json-schema-9b1349a/json-schema.gemspec000066400000000000000000000014041515251074100221040ustar00rootroot00000000000000Gem::Specification.new do |s| s.name = 'json-schema' s.version = '6.2.0' s.authors = ['Kenny Hoxworth', 'Vox Pupuli'] s.email = 'voxpupuli@groups.io' s.homepage = 'https://github.com/voxpupuli/json-schema/' s.metadata = { 'source_code_uri' => s.homepage, 'changelog_uri' => "#{s.homepage}/blob/master/CHANGELOG.md", 'bug_tracker_uri' => "#{s.homepage}/issues", 'funding_uri' => 'https://github.com/sponsors/voxpupuli', } 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 = '>= 2.7' s.license = 'MIT' s.add_dependency 'addressable', '~> 2.8' s.add_dependency 'bigdecimal', '>= 3.1', '< 5' end voxpupuli-json-schema-9b1349a/lib/000077500000000000000000000000001515251074100170775ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema.rb000066400000000000000000000013641515251074100216370ustar00rootroot00000000000000require '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')].sort.each { |file| require file } Dir[File.join(File.dirname(__FILE__), 'json-schema/validators/*.rb')].sort!.each { |file| require file } voxpupuli-json-schema-9b1349a/lib/json-schema/000077500000000000000000000000001515251074100213065ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/attribute.rb000066400000000000000000000030211515251074100236320ustar00rootroot00000000000000require '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, properties = []) error = ValidationError.new(message, fragments, failed_attribute, current_schema, properties) 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 do |(_, v)| -Array(v).map { |klass| klass.ancestors.size }.max end.find do |(_, v)| Array(v).any? { |klass| data.is_a?(klass) } end type end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/000077500000000000000000000000001515251074100234745ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/additionalitems.rb000066400000000000000000000020641515251074100271750ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/additionalproperties.rb000066400000000000000000000043341515251074100302520ustar00rootroot00000000000000require '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 -= schema['properties'].keys end schema['patternProperties']&.each_key do |key| regexp = Regexp.new(key) extra_properties.reject! { |prop| regexp.match(prop) } 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/allof.rb000066400000000000000000000056061515251074100251250ustar00rootroot00000000000000require '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 message = nil 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 # Cannot raise if noAdditionalProperties is true, we need to # evaluate each sub schema within the allOf, before raising. if options[:noAdditionalProperties] == true schema.validate(data, fragments, processor, options.merge(record_errors: true)) else schema.validate(data, fragments, processor, options) end rescue ValidationError => e valid = false message = e.message end diff = validation_errors(processor).count - pre_validation_error_count while diff > 0 diff -= 1 errors["allOf ##{schema_index}"].push(validation_errors(processor).pop) end end # Find any properties that are missing across all subschemas. common_missing_properties = {} if options[:noAdditionalProperties] == true && !errors.empty? all_property_errors = errors.values.flatten.map(&:properties) common_missing_properties = (all_property_errors.first || []).to_set all_property_errors[1..].each do |curr_property_errors| common_missing_properties &= curr_property_errors.to_set end end # PropertiesV4Attribute represents errors that would indicate an # additional property was detected. If we filter these out, we should # be left with errors that are not dependent on any other sub schema. non_missing_property_errors = errors.values.flatten.reject do |error| error.failed_attribute == JSON::Schema::PropertiesV4Attribute end if !valid || !non_missing_property_errors.empty? || !common_missing_properties.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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/anyof.rb000066400000000000000000000035011515251074100251340ustar00rootroot00000000000000require '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 -= 1 errors["anyOf ##{schema_index}"].push(validation_errors(processor).pop) end break if valid data = original_data end unless 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/const.rb000066400000000000000000000010501515251074100251430ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class ConstAttribute < Attribute def self.validate(current_schema, data, fragments, processor, _validator, options = {}) const_value = current_schema.schema['const'] unless const_value == data message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match constant '#{const_value}'" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/dependencies.rb000066400000000000000000000027711515251074100264560ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class DependenciesAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) current_schema.schema['dependencies'].each do |property, dependency_value| next unless data.has_key?(property.to_s) next unless accept_value?(dependency_value) case dependency_value when String validate_dependency(current_schema, data, property, dependency_value, fragments, processor, self, options) when Array dependency_value.each do |value| validate_dependency(current_schema, data, property, value, fragments, processor, self, options) end else schema = JSON::Schema.new(dependency_value, current_schema.uri, validator) schema.validate(data, fragments, processor, options) end end end def self.validate_dependency(schema, data, property, value, fragments, processor, attribute, options) return if data.key?(value.to_s) message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'" validation_error(processor, message, fragments, schema, attribute, options[:record_errors]) end def self.accept_value?(value) value.is_a?(String) || value.is_a?(Array) || value.is_a?(Hash) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/dependencies_v4.rb000066400000000000000000000003641515251074100270630ustar00rootroot00000000000000require 'json-schema/attributes/dependencies' module JSON class Schema class DependenciesV4Attribute < DependenciesAttribute def self.accept_value?(value) value.is_a?(Array) || value.is_a?(Hash) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/disallow.rb000066400000000000000000000006041515251074100256370ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/divisibleby.rb000066400000000000000000000012621515251074100263270ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class DivisibleByAttribute < Attribute def self.keyword 'divisibleBy' end def self.validate(current_schema, data, fragments, processor, _validator, options = {}) return unless data.is_a?(Numeric) factor = current_schema.schema[keyword] if factor == 0 || factor == 0.0 || (BigDecimal(data.to_s) % BigDecimal(factor.to_s)).to_f != 0 message = "The property '#{build_fragment(fragments)}' was not divisible by #{factor}" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/enum.rb000066400000000000000000000013721515251074100247700ustar00rootroot00000000000000require '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 do |val| case val when nil then 'null' when Array then 'array' when Hash then 'object' else val.to_s end 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/extends.rb000066400000000000000000000033241515251074100254750ustar00rootroot00000000000000require '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] unless 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}' 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 = nil schema = 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 = ref_uri schema = 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/format.rb000066400000000000000000000007541515251074100253170ustar00rootroot00000000000000require '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) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/000077500000000000000000000000001515251074100251475ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/custom.rb000066400000000000000000000012241515251074100270050ustar00rootroot00000000000000require 'json-schema/attributes/format' require 'json-schema/errors/custom_format_error' module JSON class Schema class CustomFormat < FormatAttribute def initialize(validation_proc) @validation_proc = validation_proc end def validate(current_schema, data, fragments, processor, _validator, options = {}) @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.class, options[:record_errors]) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/date.rb000066400000000000000000000015631515251074100264160ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class DateFormat < FormatAttribute REGEXP = /\A\d{4}-\d{2}-\d{2}\z/.freeze 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/date_time.rb000066400000000000000000000033161515251074100274320ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class DateTimeFormat < FormatAttribute REGEXP = /\A\d{4}-\d{2}-\d{2}T(\d{2}):(\d{2}):(\d{2})([.,]\d+)?(Z|[+-](\d{2})(:?\d{2})?)?\z/.freeze 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/date_time_v4.rb000066400000000000000000000010531515251074100300370ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class DateTimeV4Format < FormatAttribute def self.validate(current_schema, data, fragments, processor, _validator, options = {}) return unless data.is_a?(String) DateTime.rfc3339(data) rescue ArgumentError error_message = "The property '#{build_fragment(fragments)}' must be a valid RFC3339 date/time string" validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/ip.rb000066400000000000000000000020361515251074100261050ustar00rootroot00000000000000require '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.start_with?('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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/time.rb000066400000000000000000000020231515251074100264270ustar00rootroot00000000000000require 'json-schema/attributes/format' module JSON class Schema class TimeFormat < FormatAttribute REGEXP = /\A(\d{2}):(\d{2}):(\d{2})\z/.freeze 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/formats/uri.rb000066400000000000000000000011441515251074100262730ustar00rootroot00000000000000require 'json-schema/attributes/format' require 'json-schema/errors/uri_error' module JSON class Schema class UriFormat < FormatAttribute def self.validate(current_schema, data, fragments, processor, _validator, options = {}) return unless data.is_a?(String) error_message = "The property '#{build_fragment(fragments)}' must be a valid URI" begin JSON::Util::URI.parse(data) rescue JSON::Schema::UriError validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) end end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/items.rb000066400000000000000000000015211515251074100251410ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limit.rb000066400000000000000000000024271515251074100251440ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class LimitAttribute < Attribute def self.validate(current_schema, data, fragments, processor, _validator, options = {}) schema = current_schema.schema return unless data.is_a?(acceptable_type) && invalid?(schema, value(data)) property = build_fragment(fragments) description = error_message(schema) message = format("The property '%s' %s", property, description) validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end def self.invalid?(schema, data) exclusive = exclusive?(schema) limit = limit(schema) if limit_name.start_with?('max') exclusive ? data >= limit : data > limit else exclusive ? data <= limit : data < limit end end def self.limit(schema) schema[limit_name] end def self.exclusive?(_schema) false end def self.value(data) data end def self.acceptable_type raise NotImplementedError end def self.error_message(schema) raise NotImplementedError end def self.limit_name raise NotImplementedError end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/000077500000000000000000000000001515251074100247755ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/items.rb000066400000000000000000000003651515251074100264470ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class ItemsLimitAttribute < LimitAttribute def self.acceptable_type Array end def self.value(data) data.length end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/length.rb000066400000000000000000000003671515251074100266110ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class LengthLimitAttribute < LimitAttribute def self.acceptable_type String end def self.value(data) data.length end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/max_items.rb000066400000000000000000000004601515251074100273100ustar00rootroot00000000000000require 'json-schema/attributes/limits/items' module JSON class Schema class MaxItemsAttribute < ItemsLimitAttribute def self.limit_name 'maxItems' end def self.error_message(schema) "had more items than the allowed #{limit(schema)}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/max_length.rb000066400000000000000000000004721515251074100274530ustar00rootroot00000000000000require 'json-schema/attributes/limits/length' module JSON class Schema class MaxLengthAttribute < LengthLimitAttribute def self.limit_name 'maxLength' end def self.error_message(schema) "was not of a maximum string length of #{limit(schema)}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/max_properties.rb000066400000000000000000000005111515251074100303600ustar00rootroot00000000000000require 'json-schema/attributes/limits/properties' module JSON class Schema class MaxPropertiesAttribute < PropertiesLimitAttribute def self.limit_name 'maxProperties' end def self.error_message(schema) "had more properties than the allowed #{limit(schema)}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/maximum.rb000066400000000000000000000004271515251074100270020ustar00rootroot00000000000000require 'json-schema/attributes/limits/numeric' module JSON class Schema class MaximumAttribute < NumericLimitAttribute def self.limit_name 'maximum' end def self.exclusive?(schema) schema['exclusiveMaximum'] end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/maximum_inclusive.rb000066400000000000000000000003541515251074100310620ustar00rootroot00000000000000require 'json-schema/attributes/limits/maximum' module JSON class Schema class MaximumInclusiveAttribute < MaximumAttribute def self.exclusive?(schema) schema['maximumCanEqual'] == false end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/min_items.rb000066400000000000000000000004721515251074100273110ustar00rootroot00000000000000require 'json-schema/attributes/limits/items' module JSON class Schema class MinItemsAttribute < ItemsLimitAttribute def self.limit_name 'minItems' end def self.error_message(schema) "did not contain a minimum number of items #{limit(schema)}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/min_length.rb000066400000000000000000000004721515251074100274510ustar00rootroot00000000000000require 'json-schema/attributes/limits/length' module JSON class Schema class MinLengthAttribute < LengthLimitAttribute def self.limit_name 'minLength' end def self.error_message(schema) "was not of a minimum string length of #{limit(schema)}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/min_properties.rb000066400000000000000000000005231515251074100303610ustar00rootroot00000000000000require 'json-schema/attributes/limits/properties' module JSON class Schema class MinPropertiesAttribute < PropertiesLimitAttribute def self.limit_name 'minProperties' end def self.error_message(schema) "did not contain a minimum number of properties #{limit(schema)}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/minimum.rb000066400000000000000000000004271515251074100270000ustar00rootroot00000000000000require 'json-schema/attributes/limits/numeric' module JSON class Schema class MinimumAttribute < NumericLimitAttribute def self.limit_name 'minimum' end def self.exclusive?(schema) schema['exclusiveMinimum'] end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/minimum_inclusive.rb000066400000000000000000000003541515251074100310600ustar00rootroot00000000000000require 'json-schema/attributes/limits/minimum' module JSON class Schema class MinimumInclusiveAttribute < MinimumAttribute def self.exclusive?(schema) schema['minimumCanEqual'] == false end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/numeric.rb000066400000000000000000000006241515251074100267660ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class NumericLimitAttribute < LimitAttribute def self.acceptable_type Numeric end def self.error_message(schema) exclusivity = exclusive?(schema) ? 'exclusively' : 'inclusively' format('did not have a %s value of %s, %s', limit_name, limit(schema), exclusivity) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/limits/properties.rb000066400000000000000000000003671515251074100275240ustar00rootroot00000000000000require 'json-schema/attributes/limit' module JSON class Schema class PropertiesLimitAttribute < LimitAttribute def self.acceptable_type Hash end def self.value(data) data.size end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/maxdecimal.rb000066400000000000000000000012241515251074100261240ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/multipleof.rb000066400000000000000000000003061515251074100262000ustar00rootroot00000000000000require 'json-schema/attributes/divisibleby' module JSON class Schema class MultipleOfAttribute < DivisibleByAttribute def self.keyword 'multipleOf' end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/not.rb000066400000000000000000000021621515251074100246220ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/oneof.rb000066400000000000000000000036541515251074100251370ustar00rootroot00000000000000require '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 unless valid while diff > 0 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 message = if validation_error_count == one_of.length "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match any of the required schemas" else "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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/pattern.rb000066400000000000000000000011641515251074100255000ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/patternproperties.rb000066400000000000000000000013471515251074100276200ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/properties.rb000066400000000000000000000046161515251074100262240ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class PropertiesAttribute < Attribute def self.required?(schema, options) schema.fetch('required') { options[:allPropertiesRequired] } 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 noAdditionalProperties is true, ensure no undefined properties exist in the data return unless options[:noAdditionalProperties] == 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 unless diff.empty? 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], diff.keys) end end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/properties_optional.rb000066400000000000000000000017171515251074100301300ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/properties_v4.rb000066400000000000000000000006041515251074100266260ustar00rootroot00000000000000require 'json-schema/attributes/properties' module JSON class Schema class PropertiesV4Attribute < PropertiesAttribute # draft4 relies on its own RequiredAttribute validation at a higher level, rather than # as an attribute of individual properties. def self.required?(_schema, options) options[:allPropertiesRequired] == true end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/propertynames.rb000066400000000000000000000015501515251074100267320ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class PropertyNames < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) return unless data.is_a?(Hash) propnames = current_schema.schema['propertyNames'] if propnames.is_a?(Hash) schema = JSON::Schema.new(propnames, current_schema.uri, validator) data.each_key do |key| schema.validate(key, fragments + [key], processor, options) end elsif propnames == false && data.any? message = "The property '#{build_fragment(fragments)}' contains additional properties #{data.keys.inspect} outside of the schema when none are allowed" validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) end end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/ref.rb000066400000000000000000000044671515251074100246100ustar00rootroot00000000000000require '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}' 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 = nil schema = 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| next unless fragment && fragment != '' fragment = fragment.gsub('~0', '~').gsub('~1', '/') target_schema = if target_schema.is_a?(Array) target_schema[fragment.to_i] else target_schema[fragment] end fragment_path += "/#{fragment}" if target_schema.nil? raise SchemaError, "The fragment '#{fragment_path}' does not exist on schema #{ref_schema.uri}" 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/required.rb000066400000000000000000000020361515251074100256420ustar00rootroot00000000000000require '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'] unless 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/type.rb000066400000000000000000000057401515251074100250100ustar00rootroot00000000000000require 'json-schema/attribute' module JSON class Schema class TypeAttribute < Attribute def self.validate(current_schema, data, fragments, processor, validator, options = {}) union = true types = if options[:disallow] current_schema.schema['disallow'] else current_schema.schema['type'] end unless 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 -= 1 union_errors["type ##{type_index}"].push(validation_errors(processor).pop) end end break if valid end if options[:disallow] return unless 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/type_v4.rb000066400000000000000000000016171515251074100254200ustar00rootroot00000000000000require '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'] unless 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 voxpupuli-json-schema-9b1349a/lib/json-schema/attributes/uniqueitems.rb000066400000000000000000000007771515251074100264040ustar00rootroot00000000000000require '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 voxpupuli-json-schema-9b1349a/lib/json-schema/errors/000077500000000000000000000000001515251074100226225ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/errors/custom_format_error.rb000066400000000000000000000001311515251074100272350ustar00rootroot00000000000000module JSON class Schema class CustomFormatError < StandardError end end end voxpupuli-json-schema-9b1349a/lib/json-schema/errors/json_load_error.rb000066400000000000000000000001251515251074100263260ustar00rootroot00000000000000module JSON class Schema class JsonLoadError < StandardError end end end voxpupuli-json-schema-9b1349a/lib/json-schema/errors/json_parse_error.rb000066400000000000000000000001261515251074100265220ustar00rootroot00000000000000module JSON class Schema class JsonParseError < StandardError end end end voxpupuli-json-schema-9b1349a/lib/json-schema/errors/schema_error.rb000066400000000000000000000001231515251074100256140ustar00rootroot00000000000000module JSON class Schema class SchemaError < StandardError end end end voxpupuli-json-schema-9b1349a/lib/json-schema/errors/schema_parse_error.rb000066400000000000000000000001631515251074100270120ustar00rootroot00000000000000require 'json/common' module JSON class Schema class SchemaParseError < JSON::ParserError end end end voxpupuli-json-schema-9b1349a/lib/json-schema/errors/uri_error.rb000066400000000000000000000001201515251074100251500ustar00rootroot00000000000000module JSON class Schema class UriError < StandardError end end end voxpupuli-json-schema-9b1349a/lib/json-schema/errors/validation_error.rb000066400000000000000000000032271515251074100265160ustar00rootroot00000000000000module JSON class Schema class ValidationError < StandardError INDENT = ' ' attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message, :properties def initialize(message, fragments, failed_attribute, schema, properties = []) @fragments = fragments.clone @schema = schema @sub_errors = {} @failed_attribute = failed_attribute @message = message @properties = properties 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 } unless @sub_errors.empty? base[:errors] = @sub_errors.each_with_object({}) do |(subschema, errors), hsh| subschema_sym = subschema.downcase.gsub(/\W+/, '_').to_sym hsh[subschema_sym] = Array(errors).map { |e| e.to_hash } end end base end def message_with_schema "#{message} in schema #{schema.uri}" end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/schema.rb000066400000000000000000000033241515251074100230750ustar00rootroot00000000000000require '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'].is_a?(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 @validator = if @schema['$schema'] JSON::Validator.validator_for_uri(@schema['$schema']) elsif parent_validator parent_validator else 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 schema.map { |key, _value| [key.to_s, stringify(schema[key])] }.to_h when Array schema.map do |schema_item| stringify(schema_item) end when Symbol 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 voxpupuli-json-schema-9b1349a/lib/json-schema/schema/000077500000000000000000000000001515251074100225465ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/schema/reader.rb000066400000000000000000000107011515251074100243340ustar00rootroot00000000000000require '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) 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 voxpupuli-json-schema-9b1349a/lib/json-schema/schema/validator.rb000066400000000000000000000022341515251074100250610ustar00rootroot00000000000000module 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', __dir__) File.join(resources, @metaschema_name) end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/util/000077500000000000000000000000001515251074100222635ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/util/array_set.rb000066400000000000000000000007701515251074100246050ustar00rootroot00000000000000# 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) unless defined? @values @values = Set.new 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 voxpupuli-json-schema-9b1349a/lib/json-schema/util/uri.rb000066400000000000000000000071471515251074100234200ustar00rootroot00000000000000# frozen_string_literal: true require 'addressable/uri' module JSON module Util # @api private class URI < Addressable::URI SUPPORTED_PROTOCOLS = %w[http https ftp tftp sftp ssh svn+ssh telnet nntp gopher wais ldap prospero] class << self alias unescape_uri unescape # @param uri [String, Addressable::URI] # @return [Addressable::URI, nil] def parse(uri) super rescue Addressable::URI::InvalidURIError => e raise JSON::Schema::UriError, e.message end # @param uri [String, Addressable::URI] # @return [Addressable::URI, nil] def file_uri(uri) convert_path(parse(uri).path) end # @param uri [String, Addressable::URI # @return [String] def unescaped_path(uri) parse(uri).unescaped_path end # Strips the fragment from the URI. # @param uri [String, Addressable::URI] # @return [Addressable::URI] def strip_fragment(uri) parse(uri).strip_fragment end # @param uri [String, Addressable::URI] # @return [Addressable::URI] def normalized_uri(uri, base_path = Dir.pwd) parse(uri).normalized_uri(base_path) end # Normalizes the reference URI based on the provided base URI # # @param ref [String, Addressable::URI] # @param base [String, Addressable::URI] # @return [Addressable::URI] def normalize_ref(ref, base) parse(ref).normalize_ref(base) end def absolutize_ref(ref, base) parse(ref).absolutize_ref(base) end end # Unencodes any percent encoded characters within a path component. # # @return [String] def unescaped_path self.class.unescape_component(path) end # Strips the fragment from the URI. # @return [Addressable::URI] a new instance of URI without a fragment def strip_fragment if fragment.nil? || fragment.empty? self else merge(fragment: '') end end # Normalizes the URI based on the provided base path. # # @param base_path [String] the base path to use for relative URIs. Defaults to the current working directory. # @return [Addressable::URI] the normalized URI or nil def normalized_uri(base_path = Dir.pwd) if relative? if path[0, 1] == '/' self.class.file_uri(self) else self.class.file_uri(File.join(base_path, self)) end else self end end # @param base [Addressable::URI, String] # @return [Addressable::URI] def normalize_ref(base) base_uri = self.class.parse(base) defer_validation do if relative? # Check for absolute path path, fragment = to_s.split('#') merge!(base_uri) if path.nil? || path == '' self.path = base_uri.path elsif path[0, 1] == '/' self.path = Pathname.new(path).cleanpath.to_s else join!(path) end self.fragment = fragment end self.fragment = '' if self.fragment.nil? || self.fragment.empty? end self end # @param base [Addressable::URI, String] # @return [Addressable::URI] def absolutize_ref(base) ref = strip_fragment if ref.absolute? ref else self.class.strip_fragment(base).join(ref.path).normalized_uri end end end end end voxpupuli-json-schema-9b1349a/lib/json-schema/util/uuid.rb000077500000000000000000000203641515251074100235660ustar00rootroot00000000000000#!/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 mask(v, str) 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 private :mask # 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 # 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 nnode = node.bytes.to_a nnode[0] |= 0x01 node = '' nnode.each { |s| node << s.chr } 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? # UUID epoch is 1582/Oct/15 tt = Time.now t = (tt.to_i * 10_000_000) + (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 &= 0xFFFF th = t >> 48 th &= 0x0FFF th |= 0x1000 cl = c & 0xFF ch = c & 0x3F00 ch >>= 8 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(/\Aurn:uuid:/, '') str.gsub!(/[^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] = format '%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:' + to_s end alias urn to_uri # Convert into 128-bit unsigned integer def to_int tmp = 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 nil end # Two UUIDs are said to be equal if and only if their (byte-order # canonicalized) integer representations are equivalent. 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 end voxpupuli-json-schema-9b1349a/lib/json-schema/validator.rb000066400000000000000000000513631515251074100236300ustar00rootroot00000000000000require 'open-uri' require 'pathname' require 'bigdecimal' require 'digest/sha1' require 'date' require 'timeout' require 'stringio' require 'yaml' require 'delegate' 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, allPropertiesRequired: false, noAdditionalProperties: false, parse_data: true, parse_integer: true, } @@validators = {} @@default_validator = nil @@available_json_backends = [] @@json_backend = nil @@serializer = nil @@use_multi_json = defined?(MultiJson) ? true : false @@multi_json_warned = false @@mutex = Mutex.new def initialize(schema_data, opts = {}) @options = @@default_opts.clone.merge(opts) configured_validator = self.class.validator_for_name(@options[:version]) @options[:schema_reader] ||= self.class.schema_reader @validation_options = @options[:record_errors] ? { record_errors: true } : {} @validation_options[:insert_defaults] = true if @options[:insert_defaults] if @options[:strict] == true @validation_options[:allPropertiesRequired] = true @validation_options[:noAdditionalProperties] = true else @validation_options[:allPropertiesRequired] = true if @options[:allPropertiesRequired] @validation_options[:noAdditionalProperties] = true if @options[:noAdditionalProperties] end @validation_options[:clear_cache] = true if !@@cache_schemas || @options[:clear_cache] @@mutex.synchronize { @base_schema = initialize_schema(schema_data, configured_validator) } @@mutex.synchronize { build_schemas(@base_schema) } # validate the schema, if requested if @options[:validate_schema] # Don't clear the cache during metaschema validation! meta_validator = self.class.new(@base_schema.validator.metaschema, { clear_cache: false }) meta_validator.validate(@base_schema.schema) 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('/').map { |f| f.gsub('~0', '~').gsub('~1', '/') } # ensure the first element was a hash, per the fragment spec if fragments.shift != '#' raise JSON::Schema::SchemaError, 'Invalid fragment syntax in :fragment option' end schema_fragment = base_schema.schema fragments.each do |f| case schema_fragment when Hash schema_fragment = schema_fragment[f] when Array schema_fragment = schema_fragment[f.to_i] end end unless schema_fragment.is_a?(Hash) raise JSON::Schema::SchemaError, 'Invalid fragment resolution for :fragment option' end schema = JSON::Schema.new(schema_fragment, schema_uri, base_schema.validator) if @options[:list] schema.to_array_schema elsif schema.is_a?(Hash) JSON::Schema.new(schema, schema_uri, @options[:version]) else schema end end class ErrorRecorder < SimpleDelegator def initialize(sub) @errors = [] super end def validation_error(error) @errors.push(error) end def validation_errors @errors end def with_errors self end end def with_errors ErrorRecorder.new(self) end # Run a simple true/false validation of data against a schema def validate(data) original_data = data data = initialize_data(data) error_recorder = with_errors @base_schema.validate(data, [], error_recorder, @validation_options) if @options[:record_errors] if @options[:errors_as_objects] error_recorder.validation_errors.map { |e| e.to_hash } else error_recorder.validation_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 %w[type disallow].each do |key| next unless schema[key].is_a?(Array) schema[key].each do |type| if type.is_a?(Hash) handle_schema(parent_schema, type) 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 class << self def validate(schema, data, opts = {}) validate!(schema, data, opts) rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError false 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, opts) validator.validate(data) 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 = {} 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 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, "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, '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 use_multi_json? @@use_multi_json end def use_multi_json=(value) @@use_multi_json = value ? true : false if use_multi_json? == false ensure_ruby_json_backends! end end def json_backend if use_multi_json? multi_json_deprecation_warning! MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine else @@json_backend end end def json_backend=(backend) if use_multi_json? multi_json_deprecation_warning! backend = 'json_gem' if backend == 'json' 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, "The JSON backend '#{backend}' could not be found." end end end def parse(s) if use_multi_json? multi_json_deprecation_warning! begin MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s) rescue MultiJson::ParseError => e raise JSON::Schema::JsonParseError, 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, e.message end when 'yajl' begin json = StringIO.new(s) parser = Yajl::Parser.new parser.parse(json) or raise(JSON::Schema::JsonParseError, 'The JSON could not be parsed by yajl') rescue Yajl::ParseError => e raise JSON::Schema::JsonParseError, e.message end else raise JSON::Schema::JsonParseError, "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 def ensure_ruby_json_backends! if !@@available_json_backends.empty? || !@@serializer.nil? return end 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 @@serializer = if @@json_backend == 'yajl' ->(o) { Yajl::Encoder.encode(o) } elsif @@json_backend == 'json' ->(o) { JSON.dump(o) } else ->(o) { YAML.dump(o) } end end def multi_json_deprecation_warning! unless @@multi_json_warned @@multi_json_warned = true warn '[DEPRECATION NOTICE] json-schema support for MultiJSON is deprecated and will be removed in a future version. ' \ 'To stop using MultiJSON, add `JSON::Validator.use_multi_json = false` to your application\'s initialization code.' end end private # for test usage only def reset_multi_json_deprecation_warning! @@multi_json_warned = false end end if use_multi_json? == false ensure_ruby_json_backends! end private if Gem::Specification.find_all_by_name('uuidtools').any? require 'uuidtools' @@fake_uuid_generator = ->(s) { UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s } else require 'json-schema/util/uuid' @@fake_uuid_generator = ->(s) { JSON::Util::UUID.create_v5(s, JSON::Util::UUID::Nil).to_s } end def serialize(schema) if self.class.use_multi_json? self.class.multi_json_deprecation_warning! 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, default_validator) 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(JSON::Validator.parse(schema), schema_uri, default_validator) 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 = 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 else 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) 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, default_validator) 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 # Check if the string is valid integer strict_convert = data.match?(/\A[+-]?\d+\z/) && !@options[:parse_integer] data = self.class.parse(data) unless strict_convert rescue JSON::Schema::JsonParseError begin json_uri = Util::URI.normalized_uri(data) data = self.class.parse(custom_open(json_uri)) rescue JSON::Schema::JsonLoadError, JSON::Schema::UriError # Silently discard the error - use the data as-is end end end end JSON::Schema.stringify(data) end def custom_open(uri) uri = Util::URI.normalized_uri(uri) if uri.is_a?(String) if uri.absolute? && Util::URI::SUPPORTED_PROTOCOLS.include?(uri.scheme) begin URI.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 voxpupuli-json-schema-9b1349a/lib/json-schema/validators/000077500000000000000000000000001515251074100234565ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/lib/json-schema/validators/draft1.rb000066400000000000000000000031171515251074100251660ustar00rootroot00000000000000require '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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/draft2.rb000066400000000000000000000032201515251074100251620ustar00rootroot00000000000000require '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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/draft3.rb000066400000000000000000000036441515251074100251750ustar00rootroot00000000000000require '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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/draft4.rb000066400000000000000000000044411515251074100251720ustar00rootroot00000000000000require '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(new) JSON::Validator.register_default_validator(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/draft6.rb000066400000000000000000000046161515251074100252000ustar00rootroot00000000000000require '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, 'const' => JSON::Schema::ConstAttribute, '$ref' => JSON::Schema::RefAttribute, 'propertyNames' => JSON::Schema::PropertyNames, } @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(new) JSON::Validator.register_default_validator(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/hyper-draft1.rb000066400000000000000000000003761515251074100263170ustar00rootroot00000000000000module 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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/hyper-draft2.rb000066400000000000000000000003761515251074100263200ustar00rootroot00000000000000module 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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/hyper-draft3.rb000066400000000000000000000003761515251074100263210ustar00rootroot00000000000000module 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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/hyper-draft4.rb000066400000000000000000000003761515251074100263220ustar00rootroot00000000000000module 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(new) end end end voxpupuli-json-schema-9b1349a/lib/json-schema/validators/hyper-draft6.rb000066400000000000000000000003761515251074100263240ustar00rootroot00000000000000module 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(new) end end end voxpupuli-json-schema-9b1349a/resources/000077500000000000000000000000001515251074100203435ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/resources/draft-01.json000066400000000000000000000047131515251074100225610ustar00rootroot00000000000000{ "$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" : {} }voxpupuli-json-schema-9b1349a/resources/draft-02.json000066400000000000000000000052441515251074100225620ustar00rootroot00000000000000{ "$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" : {} }voxpupuli-json-schema-9b1349a/resources/draft-03.json000066400000000000000000000074271515251074100225700ustar00rootroot00000000000000{ "$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": {} } voxpupuli-json-schema-9b1349a/resources/draft-04.json000066400000000000000000000104271515251074100225630ustar00rootroot00000000000000{ "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": {} } voxpupuli-json-schema-9b1349a/resources/draft-06.json000066400000000000000000000104071515251074100225630ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-06/schema#", "$id": "http://json-schema.org/draft-06/schema#", "title": "Core schema meta-schema", "definitions": { "schemaArray": { "type": "array", "minItems": 1, "items": { "$ref": "#" } }, "nonNegativeInteger": { "type": "integer", "minimum": 0 }, "nonNegativeIntegerDefault0": { "allOf": [ { "$ref": "#/definitions/nonNegativeInteger" }, { "default": 0 } ] }, "simpleTypes": { "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] }, "stringArray": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "default": [] } }, "type": ["object", "boolean"], "properties": { "$id": { "type": "string", "format": "uri-reference" }, "$schema": { "type": "string", "format": "uri" }, "$ref": { "type": "string", "format": "uri-reference" }, "title": { "type": "string" }, "description": { "type": "string" }, "default": {}, "multipleOf": { "type": "number", "exclusiveMinimum": 0 }, "maximum": { "type": "number" }, "exclusiveMaximum": { "type": "number" }, "minimum": { "type": "number" }, "exclusiveMinimum": { "type": "number" }, "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, "pattern": { "type": "string", "format": "regex" }, "additionalItems": { "$ref": "#" }, "items": { "anyOf": [ { "$ref": "#" }, { "$ref": "#/definitions/schemaArray" } ], "default": {} }, "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, "uniqueItems": { "type": "boolean", "default": false }, "contains": { "$ref": "#" }, "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, "required": { "$ref": "#/definitions/stringArray" }, "additionalProperties": { "$ref": "#" }, "definitions": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "properties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "patternProperties": { "type": "object", "additionalProperties": { "$ref": "#" }, "default": {} }, "dependencies": { "type": "object", "additionalProperties": { "anyOf": [ { "$ref": "#" }, { "$ref": "#/definitions/stringArray" } ] } }, "propertyNames": { "$ref": "#" }, "const": {}, "enum": { "type": "array", "minItems": 1, "uniqueItems": true }, "type": { "anyOf": [ { "$ref": "#/definitions/simpleTypes" }, { "type": "array", "items": { "$ref": "#/definitions/simpleTypes" }, "minItems": 1, "uniqueItems": true } ] }, "format": { "type": "string" }, "allOf": { "$ref": "#/definitions/schemaArray" }, "anyOf": { "$ref": "#/definitions/schemaArray" }, "oneOf": { "$ref": "#/definitions/schemaArray" }, "not": { "$ref": "#" } }, "default": {} } voxpupuli-json-schema-9b1349a/test/000077500000000000000000000000001515251074100173105ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/test/all_of_ref_schema_test.rb000066400000000000000000000035711515251074100243120ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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(%r{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 def test_all_of_ref_message_with_one_attribute_wrong 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 def test_all_of_ref_validate_messgae exception = assert_raises JSON::Schema::ValidationError do JSON::Validator.validate!(schema, data) end expected_error_message = "The property '#/name' of type string did not match the following type: integer" assert_equal expected_error_message, exception.message end end voxpupuli-json-schema-9b1349a/test/any_of_ref_schema_test.rb000066400000000000000000000030601515251074100243220ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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(%i[anyof_0 anyof_1 anyof_2], nested_errors.keys, 'should have nested errors for each anyOf subschema') assert_match(%r{the property '#/names/0' value "jack" did not match the regex 'john'}i, nested_errors[:anyof_0][0][:message]) assert_match(%r{the property '#/names/0' value "jack" did not match the regex 'jane'}i, nested_errors[:anyof_1][0][:message]) assert_match(%r{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 voxpupuli-json-schema-9b1349a/test/bad_schema_ref_test.rb000066400000000000000000000025631515251074100236040ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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', __dir__) 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 voxpupuli-json-schema-9b1349a/test/caching_test.rb000066400000000000000000000022141515251074100222670ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/common_test_suite_test.rb000066400000000000000000000037431515251074100244430ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) require 'json' class CommonTestSuiteTest < Minitest::Test TEST_DIR = File.expand_path('test-suite/tests', __dir__) IGNORED_TESTS = YAML.load_file(File.expand_path('support/test_suite_ignored_tests.yml', __dir__)) def setup Dir["#{TEST_DIR}/../remotes/**/*.json"].each do |path| schema = path.sub(%r{^.*/remotes/}, '') stub_request(:get, "http://localhost:1234/#{schema}") .to_return(body: File.read(path), status: 200) end end def self.skip?(current_test, file_path) skipped_in_file = file_path.chomp('.json').split('/').inject(IGNORED_TESTS) do |ignored, path_component| ignored.nil? ? nil : ignored[path_component] end !skipped_in_file.nil? && (skipped_in_file == :all || skipped_in_file.include?(current_test)) end Dir["#{TEST_DIR}/*"].each do |suite| version = File.basename(suite).to_sym Dir["#{suite}/**/*.json"].each do |tfile| test_list = JSON.parse(File.read(tfile)) rel_file = tfile[TEST_DIR.length + 1..] test_list.each do |test| schema = test['schema'] base_description = test['description'] test['tests'].each do |t| full_description = "#{base_description}/#{t['description']}" next if rel_file.include?('/optional/') && skip?(full_description, rel_file) err_id = "#{rel_file}: #{full_description}" define_method("test_#{err_id}") do skip if self.class.skip?(full_description, rel_file) errors = JSON::Validator.fully_validate(schema, t['data'], parse_data: false, validate_schema: true, version: version) assert_equal t['valid'], errors.empty?, "Common test suite case failed: #{err_id}" end end end end end end voxpupuli-json-schema-9b1349a/test/custom_format_test.rb000066400000000000000000000131451515251074100235620ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class CustomFormatTest < Minitest::Test def setup @all_versions = ['draft1', 'draft2', 'draft3', 'draft4', 'draft6', nil] @format_proc = ->(value) { raise JSON::Schema::CustomFormatError, '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_nil(JSON::Validator.validator_for_name(version).formats['custom'], "Format 'custom' for #{version || 'default'} should be nil") JSON::Validator.register_format_validator('custom', @format_proc, [version]) assert_kind_of(JSON::Schema::CustomFormat, JSON::Validator.validator_for_name(version).formats['custom'], "Format 'custom' should be registered for #{version || 'default'}") (@all_versions - [version]).each do |other_version| assert_nil(JSON::Validator.validator_for_name(other_version).formats['custom'], "Format 'custom' should still be nil for #{other_version || 'default'}") end JSON::Validator.deregister_format_validator('custom', [version]) assert_nil(JSON::Validator.validator_for_name(version).formats['custom'], "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_kind_of(JSON::Schema::CustomFormat, JSON::Validator.validator_for_name(version).formats['custom'], "Format 'custom' should be registered for #{version || 'default'}") end JSON::Validator.restore_default_formats @all_versions.each do |version| assert_nil(JSON::Validator.validator_for_name(version).formats['custom'], "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_kind_of(JSON::Schema::CustomFormat, JSON::Validator.validator_for_name(version).formats['custom'], "Format 'custom' should be registered for #{version || 'default'}") end assert_nil(JSON::Validator.validator_for_name(unregistered_version).formats['custom'], "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(1, errors.count) assert_match(%r{The property '#/a' must be 42 in schema}, errors.first, "#{prefix} records format error") errors_as_objects = JSON::Validator.fully_validate(schema, data, errors_as_objects: true) assert_match('CustomFormat', errors_as_objects.first[:failed_attribute], "#{prefix} tags failed attribute") data['a'] = 23 errors = JSON::Validator.fully_validate(schema, data) assert_equal(1, errors.count) assert_match(%r{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 overridden 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 voxpupuli-json-schema-9b1349a/test/data/000077500000000000000000000000001515251074100202215ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/test/data/all_of_ref_data.json000066400000000000000000000000441515251074100241730ustar00rootroot00000000000000{ "name" : "john", "id" : "1" } voxpupuli-json-schema-9b1349a/test/data/any_of_ref_data.json000066400000000000000000000000761515251074100242170ustar00rootroot00000000000000{ "names" : [ "john" , "jane" , "jimmy" ] } voxpupuli-json-schema-9b1349a/test/data/bad_data_1.json000066400000000000000000000000221515251074100230450ustar00rootroot00000000000000{ "a" : "poop" }voxpupuli-json-schema-9b1349a/test/data/good_data_1.json000066400000000000000000000000151515251074100232510ustar00rootroot00000000000000{ "a" : 5 }voxpupuli-json-schema-9b1349a/test/data/one_of_ref_links_data.json000066400000000000000000000002331515251074100254040ustar00rootroot00000000000000{ "links": [{ "rel" : ["self"] , "href":"http://api.example.com/api/object/3" } ,{ "rel" : ["up"] , "href":"http://api.example.com/api/object" } ] } voxpupuli-json-schema-9b1349a/test/draft1_test.rb000066400000000000000000000056241515251074100220640ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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'] = %w[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 voxpupuli-json-schema-9b1349a/test/draft2_test.rb000066400000000000000000000050351515251074100220610ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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'] = %w[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 voxpupuli-json-schema-9b1349a/test/draft3_test.rb000066400000000000000000000343451515251074100220700ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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_empty(errors, 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 3 } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 3 } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', '23 taco' => 3 } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', '23 taco' => 'cheese' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: 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'] = %w[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' => %w[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 voxpupuli-json-schema-9b1349a/test/draft4_test.rb000066400000000000000000000544621515251074100220730ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) module StrictValidationV4 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 3 } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 3 } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', '23 taco' => 3 } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', '23 taco' => 'cheese' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) end end 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 StrictValidationV4 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' => %w[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' => %w[view search], 'default' => 'view', }, }, }, { 'type' => 'object', 'properties' => { 'bar' => { 'type' => 'string', }, }, }, ], } data = {} assert(JSON::Validator.validate(schema, data, insert_defaults: true, strict: true)) assert_equal('view', data['foo']) end def test_default_with_strict_and_oneof schema = { 'oneOf' => [ { 'type' => 'object', 'properties' => { 'bar' => { 'type' => 'string', }, }, }, { 'type' => 'object', 'properties' => { 'foo' => { 'enum' => %w[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' => %w[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' => 5_555_555_555_555_555, } 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' => %w[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' => %w[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' => %w[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 voxpupuli-json-schema-9b1349a/test/draft6_test.rb000066400000000000000000000016611515251074100220660ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class Draft6Test < Minitest::Test def validation_errors(schema, data, _options) super(schema, data, version: :draft6) end def test_const_attribute schema = { 'type' => 'object', 'properties' => { 'a' => { 'const' => 'foo' }, 'b' => { 'const' => 6 }, }, } data = { a: 'foo', b: 6 } assert_valid schema, data data = { a: 6, b: 'foo' } refute_valid schema, data end def test_property_names schema = { 'type' => 'object', 'propertyNames' => { 'const' => 'foo' }, } data = { 'foo' => 'value' } assert_valid schema, data data = { 'bar' => 'value' } refute_valid schema, data schema = { 'type' => 'object', 'propertyNames' => false, } data = {} assert_valid schema, data data = { 'foo' => 'value' } refute_valid schema, data end end voxpupuli-json-schema-9b1349a/test/extended_schema_test.rb000066400000000000000000000044011515251074100240130ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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_extended_schema_validation_with_fragment schema = { '$schema' => 'http://test.com/test.json', 'definitions' => { 'odd-a' => { 'properties' => { 'a' => { 'bitwise-and' => 1, }, }, }, }, } assert_valid schema, { 'a' => 1 }, fragment: '#/definitions/odd-a' refute_valid schema, { 'a' => 0 }, fragment: '#/definitions/odd-a' 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 voxpupuli-json-schema-9b1349a/test/extends_nested_test.rb000066400000000000000000000026251515251074100237150ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/files_test.rb000066400000000000000000000043171515251074100220030ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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, '{"a": 5}', json: true refute_valid schema, '{"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, '{"a": 5}', json: true refute_valid schema, '{"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 voxpupuli-json-schema-9b1349a/test/fragment_resolution_test.rb000066400000000000000000000047341515251074100247720ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class FragmentResolutionTest < Minitest::Test def test_fragment_resolution schema = { '$schema' => 'http://json-schema.org/draft-04/schema#', 'required' => ['a'], 'properties' => { 'a' => { 'type' => 'object', 'properties' => { 'b' => { 'type' => 'integer' }, }, }, }, } data = { 'b' => 5 } refute_valid schema, data assert_valid schema, data, fragment: '#/properties/a' assert_raises JSON::Schema::SchemaError do JSON::Validator.validate!(schema, data, fragment: '/properties/a') end assert_raises JSON::Schema::SchemaError do JSON::Validator.validate!(schema, data, fragment: '#/properties/b') end end def test_odd_level_fragment_resolution schema = { 'foo' => { 'type' => 'object', 'required' => ['a'], 'properties' => { 'a' => { 'type' => 'integer' }, }, }, } assert_valid schema, { 'a' => 1 }, fragment: '#/foo' refute_valid schema, {}, fragment: '#/foo' end def test_even_level_fragment_resolution schema = { 'foo' => { 'bar' => { 'type' => 'object', 'required' => ['a'], 'properties' => { 'a' => { 'type' => 'integer' }, }, }, }, } assert_valid schema, { 'a' => 1 }, fragment: '#/foo/bar' refute_valid schema, {}, fragment: '#/foo/bar' end def test_array_fragment_resolution schema = { 'type' => 'object', 'required' => ['a'], 'properties' => { 'a' => { 'anyOf' => [ { 'type' => 'integer' }, { 'type' => 'string' }, ], }, }, } refute_valid schema, 'foo', fragment: '#/properties/a/anyOf/0' assert_valid schema, 'foo', fragment: '#/properties/a/anyOf/1' assert_valid schema, 5, fragment: '#/properties/a/anyOf/0' refute_valid schema, 5, fragment: '#/properties/a/anyOf/1' end def test_fragment_with_escape_sequences_resolution schema = { 'content' => { 'application/json' => { 'type' => 'object', 'required' => ['a'], 'properties' => { 'a' => { 'type' => 'integer' }, }, }, }, } assert_valid schema, { 'a' => 1 }, fragment: '#/content/application~1json' refute_valid schema, {}, fragment: '#/content/application~1json' end end voxpupuli-json-schema-9b1349a/test/fragment_validation_with_ref_test.rb000066400000000000000000000032301515251074100265760ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class FragmentValidationWithRefTest < Minitest::Test def whole_schema { '$schema' => 'http://json-schema.org/draft-04/schema#', 'type' => 'object', 'definitions' => { 'post' => { 'type' => 'object', 'properties' => { 'content' => { 'type' => 'string', }, 'author' => { 'type' => 'string', }, }, }, 'posts' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/post', }, }, }, } end def whole_schema_with_array { '$schema' => 'http://json-schema.org/draft-04/schema#', 'type' => 'object', 'definitions' => { 'omg' => { 'links' => [ { 'type' => 'object', 'schema' => { 'properties' => { 'content' => { 'type' => 'string', }, 'author' => { 'type' => 'string', }, }, 'required' => %w[content author], }, }, ], }, }, } end def test_validation_of_fragment data = [{ 'content' => 'ohai', 'author' => 'Bob' }] assert_valid whole_schema, data, fragment: '#/definitions/posts' end def test_validation_of_fragment_with_array data = { 'content' => 'ohai', 'author' => 'Bob' } assert_valid(whole_schema_with_array, data, fragment: '#/definitions/omg/links/0/schema') end end voxpupuli-json-schema-9b1349a/test/full_validation_test.rb000066400000000000000000000144201515251074100240510ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class FullValidationTest < Minitest::Test def test_frozen_validator data = { 'c' => 'a' }.freeze schema = { 'type' => 'object', 'required' => ['b'], 'properties' => { 'b' => {}, }, }.freeze assert_raises JSON::Schema::ValidationError do JSON::Validator.new(schema, { record_errors: false }).freeze.validate(data) end JSON::Validator.new(schema, { record_errors: true }).freeze.validate(data) end def test_full_validation data = { 'b' => { 'a' => 5 } } schema = { 'type' => 'object', 'required' => ['b'], 'properties' => { 'b' => {}, }, } errors = JSON::Validator.fully_validate(schema, data) assert_empty(errors) data = { 'c' => 5 } schema = { 'type' => 'object', 'required' => ['b'], 'properties' => { 'b' => {}, 'c' => { 'type' => 'string', }, }, } errors = JSON::Validator.fully_validate(schema, data) assert_equal(2, errors.length) end def test_full_validation_with_instantiated_validator data = { 'b' => { 'a' => 5 } } schema = { 'type' => 'object', 'required' => ['b'], 'properties' => { 'b' => {}, }, } validator = JSON::Validator.new(schema, { record_errors: true }) assert_empty(validator.validate(data)) assert_empty(validator.validate(data)) assert_empty(validator.validate(data)) data = { 'c' => 5 } schema = { 'type' => 'object', 'required' => ['b'], 'properties' => { 'b' => {}, 'c' => { 'type' => 'string', }, }, } validator = JSON::Validator.new(schema, { record_errors: true }) assert_equal(2, validator.validate(data).length) assert_equal(2, validator.validate(data).length) assert_equal(2, validator.validate(data).length) end def test_full_validation_with_union_types data = { 'b' => 5 } schema = { 'type' => 'object', 'properties' => { 'b' => { 'type' => %w[null integer], }, }, } errors = JSON::Validator.fully_validate(schema, data) assert_empty(errors) schema = { 'type' => 'object', 'properties' => { 'b' => { 'type' => %w[integer null], }, }, } errors = JSON::Validator.fully_validate(schema, data) assert_empty(errors) data = { 'b' => 'a string' } errors = JSON::Validator.fully_validate(schema, data) assert_equal(1, errors.length) 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_empty(errors) data = { 'b' => { 'd' => 6 } } errors = JSON::Validator.fully_validate(schema, data) assert_empty(errors) data = { 'b' => { 'c' => 6, 'd' => 'OH GOD' } } errors = JSON::Validator.fully_validate(schema, data) assert_equal(1, errors.length) 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_empty(errors) 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_equal(2, errors.length) assert_equal('Required', errors[0][:failed_attribute]) assert_equal('#/', errors[0][:fragment]) assert_equal('TypeV4', errors[1][:failed_attribute]) assert_equal('#/c', errors[1][:fragment]) end def test_full_validation_with_nested_required_properties schema = { 'type' => 'object', 'required' => ['x'], 'properties' => { 'x' => { 'type' => 'object', 'required' => %w[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' => %w[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 voxpupuli-json-schema-9b1349a/test/initialize_data_test.rb000066400000000000000000000300131515251074100240230ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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)) refute(JSON::Validator.validate(schema, data, parse_integer: false)) assert(JSON::Validator.validate(schema, data, json: true)) assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_hash_string schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } } data = '{"a": "b"}' assert(JSON::Validator.validate(schema, data)) refute(JSON::Validator.validate(schema, data, parse_data: false)) assert(JSON::Validator.validate(schema, data, json: true)) assert_raises(JSON::Schema::UriError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_json_string schema = { 'type' => 'string' } data = '"hello world"' assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert(JSON::Validator.validate(schema, data, json: true)) assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_plain_text_string schema = { 'type' => 'string' } data = 'kapow' assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, json: true) end assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_valid_uri_string schema = { 'type' => 'string' } data = 'http://foo.bar/' stub_request(:get, 'foo.bar').to_return(body: '"hello world"', status: 200) assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, json: true) end assert(JSON::Validator.validate(schema, data, uri: true)) end def test_parse_invalid_uri_string schema = { 'type' => 'string' } data = 'http://foo.bar/' stub_request(:get, 'foo.bar').to_timeout assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) stub_request(:get, 'foo.bar').to_return(status: [500, 'Internal Server Error']) assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, json: true) end assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_invalid_scheme_string schema = { 'type' => 'string' } data = 'pick one: [1, 2, 3]' assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert_raises(JSON::Schema::JsonParseError) do JSON::Validator.validate(schema, data, json: true) end assert_raises(JSON::Schema::UriError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_integer schema = { 'type' => 'integer' } data = 42 assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert_raises(TypeError) { JSON::Validator.validate(schema, data, json: true) } assert_raises(TypeError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_hash schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } } data = { 'a' => 'b' } assert(JSON::Validator.validate(schema, data)) assert(JSON::Validator.validate(schema, data, parse_data: false)) assert_raises(TypeError) { JSON::Validator.validate(schema, data, json: true) } assert_raises(TypeError) { JSON::Validator.validate(schema, data, uri: true) } end def test_parse_character_string_with_instantiated_validator schema = { 'type' => 'string' } data = 'hello world' v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } end def test_parse_integer_string_with_instantiated_validator schema = { 'type' => 'integer' } data = '42' v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert_raises(JSON::Schema::ValidationError) { v.validate(data) } assert_raises(JSON::Schema::ValidationError) { v.validate(data) } v = JSON::Validator.new(schema, { parse_integer: false }) assert_raises(JSON::Schema::ValidationError) { v.validate(data) } assert_raises(JSON::Schema::ValidationError) { v.validate(data) } v = JSON::Validator.new(schema, { json: true }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } end def test_parse_hash_string_with_instantiated_validator schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } } data = '{"a": "b"}' v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert_raises(JSON::Schema::ValidationError) { v.validate(data) } assert_raises(JSON::Schema::ValidationError) { v.validate(data) } v = JSON::Validator.new(schema, { json: true }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::UriError) { v.validate(data) } assert_raises(JSON::Schema::UriError) { v.validate(data) } end def test_parse_json_string_with_instantiated_validator schema = { 'type' => 'string' } data = '"hello world"' v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } end def test_parse_plain_text_string_with_instantiated_validator schema = { 'type' => 'string' } data = 'kapow' v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } end def test_parse_valid_uri_string_with_instantiated_validator schema = { 'type' => 'string' } data = 'http://foo.bar/' stub_request(:get, 'foo.bar').to_return(body: '"hello world"', status: 200) v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert(v.validate(data)) assert(v.validate(data)) end def test_parse_invalid_uri_string_with_instantiated_validator schema = { 'type' => 'string' } data = 'http://foo.bar/' stub_request(:get, 'foo.bar').to_timeout v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) stub_request(:get, 'foo.bar').to_return(status: [500, 'Internal Server Error']) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } assert_raises(JSON::Schema::JsonLoadError) { v.validate(data) } end def test_parse_invalid_scheme_string_with_instantiated_validator schema = { 'type' => 'string' } data = 'pick one: [1, 2, 3]' v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } assert_raises(JSON::Schema::JsonParseError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert_raises(JSON::Schema::UriError) { v.validate(data) } assert_raises(JSON::Schema::UriError) { v.validate(data) } end def test_parse_integer_with_instantiated_validator schema = { 'type' => 'integer' } data = 42 v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(TypeError) { v.validate(data) } assert_raises(TypeError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert_raises(TypeError) { v.validate(data) } assert_raises(TypeError) { v.validate(data) } end def test_parse_hash_with_instantiated_validator schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } } data = { 'a' => 'b' } v = JSON::Validator.new(schema) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { parse_data: false }) assert(v.validate(data)) assert(v.validate(data)) v = JSON::Validator.new(schema, { json: true }) assert_raises(TypeError) { v.validate(data) } assert_raises(TypeError) { v.validate(data) } v = JSON::Validator.new(schema, { uri: true }) assert_raises(TypeError) { v.validate(data) } assert_raises(TypeError) { v.validate(data) } end end voxpupuli-json-schema-9b1349a/test/list_option_test.rb000066400000000000000000000011471515251074100232420ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/load_ref_schema_test.rb000066400000000000000000000026571515251074100240010ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/merge_missing_values_test.rb000066400000000000000000000033471515251074100251120ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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_empty(original) end def test_merge_missing_values_for_empty_hash original = {} updated = {} JSON::Validator.merge_missing_values(updated, original) assert_empty(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 voxpupuli-json-schema-9b1349a/test/min_items_test.rb000066400000000000000000000006321515251074100226610ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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(1, errors.length) refute_match(/minimum/, errors[0]) assert_match(/null/, errors[0]) end end voxpupuli-json-schema-9b1349a/test/multi_json_usage_test.rb000066400000000000000000000021321515251074100242410ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class MultiJsonUsageTest < Minitest::Test def setup @original_use_multi_json = JSON::Validator.use_multi_json? JSON::Validator.send(:reset_multi_json_deprecation_warning!) end def teardown JSON::Validator.use_multi_json = @original_use_multi_json JSON::Validator.send(:reset_multi_json_deprecation_warning!) end def test_use_multi_json_is_disabled_by_default_in_tests refute_predicate(JSON::Validator, :use_multi_json?) end def test_json_backend_changes_when_multi_json_is_disabled JSON::Validator.use_multi_json = true suppress_warnings do assert_equal(MultiJson::Adapters::JsonGem, JSON::Validator.json_backend) end JSON::Validator.use_multi_json = false assert_equal('json', JSON::Validator.json_backend) end def test_deprecation_warning_when_multi_json_is_used JSON::Validator.use_multi_json = true _out, err = capture_io do JSON::Validator.json_backend end assert_match(/DEPRECATION NOTICE/, err) assert_match(/MultiJSON is deprecated/, err) end end voxpupuli-json-schema-9b1349a/test/no_additional_properties_all_of_test.rb000066400000000000000000000022371515251074100272740ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class NoAdditionalPropertiesAllOfTest < Minitest::Test def schema { '$schema': 'http://json-schema.org/draft-04/schema#', type: 'object', allOf: [ { type: 'object', properties: { a: { type: 'integer', }, }, required: ['a'], }, { type: 'object', properties: { b: { type: 'string', }, }, required: ['b'], }, ], } end def data { a: 1, b: 'hello', } end def test_all_of_ref_message assert_valid schema, data, { noAdditionalProperties: true } end def test_all_of_failures data = { a: 1, b: 'hello', c: 'something', } assert_raises JSON::Schema::ValidationError do JSON::Validator.validate!(schema, data, noAdditionalProperties: true) end data = { a: 1, b: 2, } assert_raises JSON::Schema::ValidationError do JSON::Validator.validate!(schema, data, noAdditionalProperties: true) end end end voxpupuli-json-schema-9b1349a/test/one_of_test.rb000066400000000000000000000054631515251074100221510ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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(%i[oneof_0 oneof_1 oneof_2], nested_errors.keys, 'should have nested errors for each allOf subschema') assert_match(%r{the property '#/a' of type Integer did not match the following type: string}i, nested_errors[:oneof_0][0][:message]) assert_match(%r{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 voxpupuli-json-schema-9b1349a/test/relative_definition_test.rb000066400000000000000000000010701515251074100247150ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/ruby_schema_test.rb000066400000000000000000000023361515251074100232010ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/schema_reader_test.rb000066400000000000000000000046141515251074100234630ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class SchemaReaderTest < Minitest::Test ADDRESS_SCHEMA_URI = 'http://json-schema.org/address' ADDRESS_SCHEMA_PATH = File.expand_path('schemas/address_microformat.json', __dir__) 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 voxpupuli-json-schema-9b1349a/test/schema_validation_test.rb000066400000000000000000000117401515251074100243510ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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: %i[ 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: %i[ string null ], }, created_at: { type: [ :string, ], }, biography: { type: %i[ string null ], }, }, relationships: { demographic: { type: :object, required: %i[ 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_empty 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_empty 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' => 8_517_194_300_913_402_149_003, '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 def test_validate_schema_no_additional_properties errors = JSON::Validator.fully_validate_schema(symbolized_schema, noAdditionalProperties: true) assert_equal 1, errors.size assert_match(/the property .* contained undefined properties: .*relationships/i, errors.first) schema_without_additional_properties = symbolized_schema schema_without_additional_properties.delete(:relationships) errors = JSON::Validator.fully_validate_schema(schema_without_additional_properties, noAdditionalProperties: true) assert_equal 0, errors.size end end voxpupuli-json-schema-9b1349a/test/schemas/000077500000000000000000000000001515251074100207335ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/test/schemas/address_microformat.json000066400000000000000000000012001515251074100256460ustar00rootroot00000000000000{ "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" } } voxpupuli-json-schema-9b1349a/test/schemas/all_of_ref_base_schema.json000066400000000000000000000001631515251074100262300ustar00rootroot00000000000000{ "type": "object", "properties" : { "name" : { "type": "integer" }, "id" : { "type": "string" } } } voxpupuli-json-schema-9b1349a/test/schemas/all_of_ref_schema.json000066400000000000000000000002201515251074100252300ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#", "type" : "object", "allOf" : [ { "$ref" : "all_of_ref_base_schema.json" } ] } voxpupuli-json-schema-9b1349a/test/schemas/any_of_ref_jane_schema.json000066400000000000000000000001431515251074100262500ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "jane" } voxpupuli-json-schema-9b1349a/test/schemas/any_of_ref_jimmy_schema.json000066400000000000000000000001441515251074100264610ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "jimmy" } voxpupuli-json-schema-9b1349a/test/schemas/any_of_ref_john_schema.json000066400000000000000000000001431515251074100262710ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#" , "type" : "string" , "pattern" : "john" } voxpupuli-json-schema-9b1349a/test/schemas/any_of_ref_schema.json000066400000000000000000000005421515251074100252560ustar00rootroot00000000000000{ "$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" } ] } } } } voxpupuli-json-schema-9b1349a/test/schemas/definition_schema.json000066400000000000000000000004071515251074100252770ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "description": "schema with definition", "type": "object", "properties": { "a": { "$ref": "#/definitions/foo" } }, "definitions": { "foo": { "type": "integer" } } } voxpupuli-json-schema-9b1349a/test/schemas/definition_schema_with_special_characters.json000066400000000000000000000003441515251074100322310ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "a": { "$ref": "#/definitions/foo:bar" } }, "definitions": { "foo:bar": { "type": "integer" } } } voxpupuli-json-schema-9b1349a/test/schemas/extends_and_additionalProperties_false_schema.json000066400000000000000000000011001515251074100330510ustar00rootroot00000000000000{ "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 } voxpupuli-json-schema-9b1349a/test/schemas/extends_and_patternProperties_schema.json000066400000000000000000000010461515251074100312550ustar00rootroot00000000000000{ "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" } } } voxpupuli-json-schema-9b1349a/test/schemas/good_schema_1.json000066400000000000000000000001601515251074100243130ustar00rootroot00000000000000{ "type" : "object", "properties" : { "a" : { "type" : "integer" } }, "required": ["a"] } voxpupuli-json-schema-9b1349a/test/schemas/good_schema_2.json000066400000000000000000000001731515251074100243200ustar00rootroot00000000000000{ "type" : "object", "properties" : { "b" : { "$ref" : "good_schema_1.json" } }, "required": ["b"] } voxpupuli-json-schema-9b1349a/test/schemas/good_schema_extends1.json000066400000000000000000000001571515251074100257140ustar00rootroot00000000000000{ "type" : "object", "extends": {"$ref": "good_schema_1.json"}, "properties" : { "c" : { } } } voxpupuli-json-schema-9b1349a/test/schemas/good_schema_extends2.json000066400000000000000000000002351515251074100257120ustar00rootroot00000000000000{ "type" : "object", "extends": [ {"$ref": "good_schema_1.json"}, {"$ref": "good_schema_2.json"} ], "properties" : { "c" : { } } } voxpupuli-json-schema-9b1349a/test/schemas/inner_schema.json000066400000000000000000000004171515251074100242630ustar00rootroot00000000000000{ "type": "object", "properties": { "innerA": { "description": "blah", "type":"boolean" }, "innerB": { "description": "blah", "type":"boolean" }, "innerC": { "description": "blah", "type": "boolean" } } } voxpupuli-json-schema-9b1349a/test/schemas/one_of_ref_links_schema.json000066400000000000000000000004651515251074100264540ustar00rootroot00000000000000{ "$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" } ] } } } } voxpupuli-json-schema-9b1349a/test/schemas/ref john with spaces schema.json000066400000000000000000000003061515251074100267340ustar00rootroot00000000000000{ "$schema" : "http://json-schema.org/draft-04/schema#", "type" : "object", "required" : ["first"], "properties": { "first": { "type": "string", "enum": ["john"] } } } voxpupuli-json-schema-9b1349a/test/schemas/relative_definition_schema.json000066400000000000000000000002321515251074100271660ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "a": { "$ref": "definition_schema.json#/definitions/foo" } } }voxpupuli-json-schema-9b1349a/test/schemas/self_link_schema.json000066400000000000000000000004211515251074100251110ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties" : { "rel" : { "type" : "array" , "items" : [ { "type" : "string" , "pattern" : "self" } ] } , "href" : { "type" : "string" } } } voxpupuli-json-schema-9b1349a/test/schemas/up_link_schema.json000066400000000000000000000004171515251074100246110ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#" , "type": "object" , "properties" : { "rel" : { "type" : "array" , "items" : [ { "type" : "string" , "pattern" : "up" } ] } , "href" : { "type" : "string" } } } voxpupuli-json-schema-9b1349a/test/stringify_test.rb000066400000000000000000000024131515251074100227120ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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(%w[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 voxpupuli-json-schema-9b1349a/test/support/000077500000000000000000000000001515251074100210245ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/test/support/array_validation.rb000066400000000000000000000051771515251074100247130ustar00rootroot00000000000000module ArrayValidation module ItemsTests def test_items_single_schema schema = { 'items' => { 'type' => 'string' } } assert_valid schema, [] assert_valid schema, ['a'] assert_valid schema, %w[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, %w[a ab] refute_valid schema, %w[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 voxpupuli-json-schema-9b1349a/test/support/enum_validation.rb000066400000000000000000000050621515251074100245320ustar00rootroot00000000000000module 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 voxpupuli-json-schema-9b1349a/test/support/number_validation.rb000066400000000000000000000035131515251074100250550ustar00rootroot00000000000000module 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 voxpupuli-json-schema-9b1349a/test/support/object_validation.rb000066400000000000000000000035241515251074100250350ustar00rootroot00000000000000module 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 voxpupuli-json-schema-9b1349a/test/support/strict_validation.rb000066400000000000000000000124671515251074100251050ustar00rootroot00000000000000module 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 3 } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: 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)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'b' => 'b' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b' } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 'c' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', 'c' => 3 } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', '23 taco' => 3 } assert(JSON::Validator.validate(schema, data, strict: true)) assert(JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(JSON::Validator.validate(schema, data, noAdditionalProperties: true)) data = { 'a' => 'a', 'b' => 'b', '23 taco' => 'cheese' } assert(!JSON::Validator.validate(schema, data, strict: true)) assert(!JSON::Validator.validate(schema, data, allPropertiesRequired: true)) assert(!JSON::Validator.validate(schema, data, noAdditionalProperties: true)) end end voxpupuli-json-schema-9b1349a/test/support/string_validation.rb000066400000000000000000000102011515251074100250630ustar00rootroot00000000000000module 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' => %w[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 voxpupuli-json-schema-9b1349a/test/support/test_helper.rb000066400000000000000000000031271515251074100236720ustar00rootroot00000000000000# frozen_string_literal: true require 'minitest/autorun' require 'webmock/minitest' Minitest.load_plugins require 'minitest/reporters' if ENV['GITHUB_ACTIONS'] == 'true' require 'minitest_reporters_github' Minitest::Reporters.use!([MinitestReportersGithub.new]) else Minitest::Reporters.use! end $LOAD_PATH.unshift(File.expand_path('../../lib', __dir__)) require 'json-schema' JSON::Validator.use_multi_json = false Dir[File.join(File.expand_path(__dir__), '*.rb')].sort.each do |support_file| require support_file unless support_file == __FILE__ end module Minitest class 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_empty(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 end voxpupuli-json-schema-9b1349a/test/support/test_suite_ignored_tests.yml000066400000000000000000000154741515251074100267030ustar00rootroot00000000000000# These are test files which we know fail spectacularly, either because we # don't support that functionality or because they require external # dependencies. To allow finer-grained control over which tests to run, # you can replace `:all` with an array containing the names of individual # tests to skip. draft3: ref: - ref overrides any sibling keywords/remote ref valid, maxItems ignored optional: jsregex: :all format: - validation of regular expressions/a regular expression with unclosed parens is invalid - validation of e-mail addresses/an invalid e-mail address - validation of URIs/an invalid URI - validation of URIs/an invalid protocol-relative URI Reference - validation of URIs/an invalid URI though valid URI reference - validation of host names/a host name with a component too long - validation of host names/a host name containing illegal characters - validation of host names/a host name starting with an illegal character - validation of CSS colors/an invalid CSS color code - validation of CSS colors/an invalid CSS color name - validation of CSS colors/a CSS color name containing invalid characters draft4: ref: - ref overrides any sibling keywords/remote ref valid, maxItems ignored - ref overrides any sibling keywords/ref valid, maxItems ignored optional: format: - validation of URIs/an invalid URI - validation of URIs/an invalid protocol-relative URI Reference - validation of URIs/an invalid URI though valid URI reference - validation of e-mail addresses/an invalid e-mail address - validation of host names/a host name with a component too long - validation of host names/a host name containing illegal characters - validation of host names/a host name starting with an illegal character ecmascript-regex: - ECMA 262 regex non-compliance/ECMA 262 has no support for \Z anchor from .NET bignum: - float comparison with high precision on negative numbers/comparison works for very negative numbers - float comparison with high precision/comparison works for high numbers draft6: allOf: - allOf with boolean schemas, some false/any value is invalid - allOf with boolean schemas, all false/any value is invalid - allOf with boolean schemas, all true/any value is valid anyOf: - anyOf with boolean schemas, all false/any value is invalid - anyOf with boolean schemas, all true/any value is valid - anyOf with boolean schemas, some true/any value is valid boolean_schema: :all contains: :all dependencies: - dependencies with boolean subschemas/empty object is valid - dependencies with boolean subschemas/object with both properties is invalid - dependencies with boolean subschemas/object with property having schema false is invalid - dependencies with boolean subschemas/object with property having schema true is valid - dependencies with empty array/empty object - dependencies with empty array/object with one property exclusiveMaximum: :all exclusiveMinimum: :all items: - items with boolean schema (false)/any non-empty array is invalid - items with boolean schema (false)/empty array is valid - items with boolean schema (true)/any array is valid - items with boolean schema (true)/empty array is valid - items with boolean schemas/array with one item is valid - items with boolean schemas/array with two items is invalid - items with boolean schemas/empty array is valid not: :all oneOf: - oneOf with boolean schemas, all false/any value is invalid - oneOf with boolean schemas, all true/any value is invalid - oneOf with boolean schemas, one true/any value is valid - oneOf with boolean schemas, more than one true/any value is invalid patternProperties: - patternProperties with boolean schemas/object with property matching schema false is invalid - patternProperties with boolean schemas/object with both properties is invalid - patternProperties with boolean schemas/object with property matching schema true is valid - patternProperties with boolean schemas/empty object is valid properties: - properties with boolean schema/only 'true' property present is valid - properties with boolean schema/only 'false' property present is invalid - properties with boolean schema/no property present is valid - properties with boolean schema/both properties present is invalid propertyNames: :all ref: - ref overrides any sibling keywords/remote ref valid, maxItems ignored - ref overrides any sibling keywords/ref valid, maxItems ignored - $ref to boolean schema true/any value is valid - $ref to boolean schema false/any value is invalid required: - required with empty array/property not required optional: bignum: - float comparison with high precision/comparison works for high numbers - float comparison with high precision on negative numbers/comparison works for very negative numbers format: - validation of URIs/an invalid URI - validation of URIs/an invalid protocol-relative URI Reference - validation of URIs/an invalid URI though valid URI reference - validation of e-mail addresses/an invalid e-mail address - validation of host names/a host name with a component too long - validation of host names/a host name containing illegal characters - validation of host names/a host name starting with an illegal character ecmascript-regex: - ECMA 262 regex non-compliance/ECMA 262 has no support for \Z anchor from .NET zeroTerminatedFloats: - some languages do not distinguish between different types of numeric value/a float is not an integer even without fractional part draft7: optional: format: date: :all date-time: :all email: :all hostname: :all idn-email: :all idn-hostname: :all ipv4: :all ipv6: :all iri: :all iri-reference: :all json-pointer: :all regex: :all relative-json-pointer: :all time: :all uri: :all uri-reference: :all uri-template: :all bignum: :all content: :all ecmascript-regex: :all zeroTerminatedFloats: :all additionalItems: :all additionalProperties: :all allOf: :all anyOf: :all boolean_schema: :all const: :all contains: :all default: :all definitions: :all dependencies: :all enum: :all exclusiveMaximum: :all exclusiveMinimum: :all if-then-else: :all items: :all maximum: :all maxItems: :all maxLength: :all maxProperties: :all minimum: :all minItems: :all minLength: :all minProperties: :all multipleOf: :all not: :all oneOf: :all pattern: :all patternProperties: :all properties: :all propertyNames: :all ref: :all refRemote: :all required: :all type: :all uniqueItems: :all voxpupuli-json-schema-9b1349a/test/support/type_validation.rb000066400000000000000000000040511515251074100245440ustar00rootroot00000000000000module 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' => %w[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.each_value 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 voxpupuli-json-schema-9b1349a/test/test-suite/000077500000000000000000000000001515251074100214165ustar00rootroot00000000000000voxpupuli-json-schema-9b1349a/test/type_attribute_test.rb000066400000000000000000000011371515251074100237420ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class TypeAttributeTest < Minitest::Test def test_type_of_data assert_equal('string', type_of_data('')) assert_equal('number', type_of_data(Numeric.new)) assert_equal('integer', type_of_data(1)) assert_equal('boolean', type_of_data(true)) assert_equal('boolean', type_of_data(false)) assert_equal('object', type_of_data({})) assert_equal('null', type_of_data(nil)) assert_equal('any', type_of_data(Object.new)) end private def type_of_data(data) JSON::Schema::TypeAttribute.type_of_data(data) end end voxpupuli-json-schema-9b1349a/test/uri_parsing_test.rb000066400000000000000000000032631515251074100232220ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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 voxpupuli-json-schema-9b1349a/test/uri_util_test.rb000066400000000000000000000140011515251074100225240ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) class UriUtilTest < Minitest::Test 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_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/#'), 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_scheme_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 voxpupuli-json-schema-9b1349a/test/validator_schema_reader_test.rb000066400000000000000000000030021515251074100255160ustar00rootroot00000000000000require File.expand_path('support/test_helper', __dir__) 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, %w[abc def], schema_reader: reader, list: true refute_valid schema, %w[abc a], schema_reader: reader, list: true end end