New Upstream Snapshot - ruby-json-schemer

Ready changes

Summary

Merged new upstream version: 0.2.24 (was: 0.2.18).

Resulting package

Built on 2023-01-11T02:26 (took 3m50s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots ruby-json-schemer

Lintian Result

Diff

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index b8013c1..0000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: ci
-on: [push, pull_request]
-jobs:
-  test:
-    strategy:
-      fail-fast: false
-      matrix:
-        os: [ubuntu-latest, windows-latest, macos-latest]
-        ruby: [2.4, 2.5, 2.6, 2.7, 3.0, head, jruby, jruby-head, truffleruby, truffleruby-head]
-        exclude:
-          - os: windows-latest
-            ruby: jruby
-          - os: windows-latest
-            ruby: jruby-head
-          - os: windows-latest
-            ruby: truffleruby
-          - os: windows-latest
-            ruby: truffleruby-head
-    runs-on: ${{ matrix.os }}
-    steps:
-    - uses: actions/checkout@v2
-    - uses: ruby/setup-ruby@v1
-      with:
-        ruby-version: ${{ matrix.ruby }}
-        bundler-cache: true
-    - run: bundle exec rake test
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index cbe7697..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-/.bundle/
-/.yardoc
-/_yardoc/
-/coverage/
-/doc/
-/pkg/
-/spec/reports/
-/tmp/
-/.ruby-version
diff --git a/Gemfile.lock b/Gemfile.lock
index 9f65db4..6a90b6a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,7 @@
 PATH
   remote: .
   specs:
-    json_schemer (0.2.18)
+    json_schemer (0.2.24)
       ecma-re-validator (~> 0.3)
       hana (~> 1.3)
       regexp_parser (~> 2.0)
@@ -13,9 +13,9 @@ GEM
     ecma-re-validator (0.3.0)
       regexp_parser (~> 2.0)
     hana (1.3.7)
-    minitest (5.14.3)
-    rake (13.0.1)
-    regexp_parser (2.1.1)
+    minitest (5.15.0)
+    rake (13.0.6)
+    regexp_parser (2.6.1)
     uri_template (0.7.0)
 
 PLATFORMS
@@ -28,4 +28,4 @@ DEPENDENCIES
   rake (~> 13.0)
 
 BUNDLED WITH
-   2.2.11
+   2.3.25
diff --git a/JSON-Schema-Test-Suite/.gitignore b/JSON-Schema-Test-Suite/.gitignore
new file mode 100644
index 0000000..1333ed7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/.gitignore
@@ -0,0 +1 @@
+TODO
diff --git a/JSON-Schema-Test-Suite/.travis.yml b/JSON-Schema-Test-Suite/.travis.yml
new file mode 100644
index 0000000..f65e40b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/.travis.yml
@@ -0,0 +1,8 @@
+language: python
+python: "3.7"
+node_js: "9"
+install:
+  - pip install tox
+script:
+  - tox
+  - npm install && npm test || true
diff --git a/JSON-Schema-Test-Suite/LICENSE b/JSON-Schema-Test-Suite/LICENSE
new file mode 100644
index 0000000..c28adba
--- /dev/null
+++ b/JSON-Schema-Test-Suite/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Julian Berman
+
+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.
diff --git a/JSON-Schema-Test-Suite/README.md b/JSON-Schema-Test-Suite/README.md
new file mode 100644
index 0000000..f65934c
--- /dev/null
+++ b/JSON-Schema-Test-Suite/README.md
@@ -0,0 +1,181 @@
+JSON Schema Test Suite [![Build Status](https://travis-ci.org/json-schema-org/JSON-Schema-Test-Suite.svg?branch=master)](https://travis-ci.org/json-schema-org/JSON-Schema-Test-Suite)
+======================
+
+This repository contains a set of JSON objects that implementors of JSON Schema
+validation libraries can use to test their validators.
+
+It is meant to be language agnostic and should require only a JSON parser.
+
+The conversion of the JSON objects into tests within your test framework of
+choice is still the job of the validator implementor.
+
+Structure of a Test
+-------------------
+
+If you're going to use this suite, you need to know how tests are laid out. The
+tests are contained in the `tests` directory at the root of this repository.
+
+Inside that directory is a subdirectory for each draft or version of the
+schema.
+
+If you look inside the draft directory, there are a number of `.json` files,
+which logically group a set of test cases together. Often the grouping is by
+property under test, but not always, especially within optional test files
+(discussed below).
+
+Inside each `.json` file is a single array containing objects. It's easiest to
+illustrate the structure of these with an example:
+
+```json
+    {
+        "description": "the description of the test case",
+        "schema": {"the schema that should" : "be validated against"},
+        "tests": [
+            {
+                "description": "a specific test of a valid instance",
+                "data": "the instance",
+                "valid": true
+            },
+            {
+                "description": "another specific test this time, invalid",
+                "data": 15,
+                "valid": false
+            }
+        ]
+    }
+```
+
+So a description, a schema, and some tests, where tests is an array containing
+one or more objects with descriptions, data, and a boolean indicating whether
+they should be valid or invalid.
+
+Coverage
+--------
+
+Drafts 03, 04, 06, and 07 should have full coverage, with drafts 06 and 07
+being considered current and actively supported.  Bug fixes will be made as
+needed for draft-04 as it is still the most widely used, while draft-03
+is long since deprecated.
+
+If you see anything missing from the current supported drafts, or incorrect
+on any draft still accepting bug fixes, please file an issue or submit a PR.
+
+Who Uses the Test Suite
+-----------------------
+
+This suite is being used by:
+
+### Clojure ###
+
+* [jinx](https://github.com/juxt/jinx)
+* [json-schema](https://github.com/tatut/json-schema)
+
+### Coffeescript ###
+
+* [jsck](https://github.com/pandastrike/jsck)
+
+### C++ ###
+
+* [Modern C++ JSON schema validator](https://github.com/pboettch/json-schema-validator)
+
+### Dart ###
+
+* [json_schema](https://github.com/patefacio/json_schema)
+
+### Elixir ###
+
+* [ex_json_schema](https://github.com/jonasschmidt/ex_json_schema)
+
+### Erlang ###
+
+* [jesse](https://github.com/for-GET/jesse)
+
+### Go ###
+
+* [gojsonschema](https://github.com/sigu-399/gojsonschema)
+* [validate-json](https://github.com/cesanta/validate-json)
+
+### Haskell ###
+
+* [aeson-schema](https://github.com/timjb/aeson-schema)
+* [hjsonschema](https://github.com/seagreen/hjsonschema)
+
+### Java ###
+
+* [json-schema-validator](https://github.com/daveclayton/json-schema-validator)
+* [everit-org/json-schema](https://github.com/everit-org/json-schema)
+* [networknt/json-schema-validator](https://github.com/networknt/json-schema-validator)
+* [Justify](https://github.com/leadpony/justify)
+
+### JavaScript ###
+
+* [json-schema-benchmark](https://github.com/Muscula/json-schema-benchmark)
+* [direct-schema](https://github.com/IreneKnapp/direct-schema)
+* [is-my-json-valid](https://github.com/mafintosh/is-my-json-valid)
+* [jassi](https://github.com/iclanzan/jassi)
+* [JaySchema](https://github.com/natesilva/jayschema)
+* [json-schema-valid](https://github.com/ericgj/json-schema-valid)
+* [Jsonary](https://github.com/jsonary-js/jsonary)
+* [jsonschema](https://github.com/tdegrunt/jsonschema)
+* [request-validator](https://github.com/bugventure/request-validator)
+* [skeemas](https://github.com/Prestaul/skeemas)
+* [tv4](https://github.com/geraintluff/tv4)
+* [z-schema](https://github.com/zaggino/z-schema)
+* [jsen](https://github.com/bugventure/jsen)
+* [ajv](https://github.com/epoberezkin/ajv)
+* [djv](https://github.com/korzio/djv)
+
+### Node.js ###
+
+For node.js developers, the suite is also available as an
+[npm](https://www.npmjs.com/package/@json-schema-org/tests) package.
+
+Node-specific support is maintained in a [separate
+repository](https://github.com/json-schema-org/json-schema-test-suite-npm)
+which also welcomes your contributions!
+
+### .NET ###
+
+* [Newtonsoft.Json.Schema](https://github.com/JamesNK/Newtonsoft.Json.Schema)
+* [Manatee.Json](https://github.com/gregsdennis/Manatee.Json)
+
+### PHP ###
+
+* [json-schema](https://github.com/justinrainbow/json-schema)
+* [json-guard](https://github.com/thephpleague/json-guard)
+
+### PostgreSQL ###
+
+* [postgres-json-schema](https://github.com/gavinwahl/postgres-json-schema)
+* [is_jsonb_valid](https://github.com/furstenheim/is_jsonb_valid)
+
+### Python ###
+
+* [jsonschema](https://github.com/Julian/jsonschema)
+* [fastjsonschema](https://github.com/seznam/python-fastjsonschema)
+* [hypothesis-jsonschema](https://github.com/Zac-HD/hypothesis-jsonschema)
+
+### Ruby ###
+
+* [json-schema](https://github.com/hoxworth/json-schema)
+* [json_schemer](https://github.com/davishmcclurg/json_schemer)
+
+### Rust ###
+
+* [valico](https://github.com/rustless/valico)
+
+### Swift ###
+
+* [JSONSchema](https://github.com/kylef/JSONSchema.swift)
+
+If you use it as well, please fork and send a pull request adding yourself to
+the list :).
+
+Contributing
+------------
+
+If you see something missing or incorrect, a pull request is most welcome!
+
+There are some sanity checks in place for testing the test suite. You can run
+them with `bin/jsonschema_suite check && npm test` or `tox && npm test`. They will be run automatically by
+[Travis CI](https://travis-ci.org/) as well.
diff --git a/JSON-Schema-Test-Suite/bin/jsonschema_suite b/JSON-Schema-Test-Suite/bin/jsonschema_suite
new file mode 100755
index 0000000..6b1c486
--- /dev/null
+++ b/JSON-Schema-Test-Suite/bin/jsonschema_suite
@@ -0,0 +1,298 @@
+#! /usr/bin/env python3
+from __future__ import print_function
+from pprint import pformat
+import argparse
+import errno
+import fnmatch
+import json
+import os
+import random
+import shutil
+import sys
+import textwrap
+import unittest
+import warnings
+
+if getattr(unittest, "skipIf", None) is None:
+    unittest.skipIf = lambda cond, msg : lambda fn : fn
+
+try:
+    import jsonschema
+except ImportError:
+    jsonschema = None
+else:
+    validators = getattr(
+        jsonschema.validators, "validators", jsonschema.validators
+    )
+
+
+ROOT_DIR = os.path.abspath(
+    os.path.join(os.path.dirname(__file__), os.pardir).rstrip("__pycache__"),
+)
+SUITE_ROOT_DIR = os.path.join(ROOT_DIR, "tests")
+
+REMOTES = {
+    "integer.json": {u"type": u"integer"},
+    "name.json": {
+        u"type": "string",
+        u"definitions": {
+            u"orNull": {u"anyOf": [{u"type": u"null"}, {u"$ref": u"#"}]},
+        },
+    },
+    "name-defs.json": {
+        u"type": "string",
+        u"$defs": {
+            u"orNull": {u"anyOf": [{u"type": u"null"}, {u"$ref": u"#"}]},
+        },
+    },
+    "subSchemas.json": {
+        u"integer": {u"type": u"integer"},
+        u"refToInteger": {u"$ref": u"#/integer"},
+    },
+    "folder/folderInteger.json": {u"type": u"integer"}
+}
+REMOTES_DIR = os.path.join(ROOT_DIR, "remotes")
+
+with open(os.path.join(ROOT_DIR, "test-schema.json")) as schema:
+    TESTSUITE_SCHEMA = json.load(schema)
+
+def files(paths):
+    for path in paths:
+        with open(path) as test_file:
+            yield json.load(test_file)
+
+
+def groups(paths):
+    for test_file in files(paths):
+        for group in test_file:
+            yield group
+
+
+def cases(paths):
+    for test_group in groups(paths):
+        for test in test_group["tests"]:
+            test["schema"] = test_group["schema"]
+            yield test
+
+
+def collect(root_dir):
+    for root, dirs, files in os.walk(root_dir):
+        for filename in fnmatch.filter(files, "*.json"):
+            yield os.path.join(root, filename)
+
+
+class SanityTests(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        print("Looking for tests in %s" % SUITE_ROOT_DIR)
+        cls.test_files = list(collect(SUITE_ROOT_DIR))
+        print("Found %s test files" % len(cls.test_files))
+        assert cls.test_files, "Didn't find the test files!"
+
+    def test_all_files_are_valid_json(self):
+        for path in self.test_files:
+            with open(path) as test_file:
+                try:
+                    json.load(test_file)
+                except ValueError as error:
+                    self.fail("%s contains invalid JSON (%s)" % (path, error))
+
+    def test_all_descriptions_have_reasonable_length(self):
+        for case in cases(self.test_files):
+            description = case["description"]
+            self.assertLess(
+                len(description),
+                70,
+                "%r is too long! (keep it to less than 70 chars)" % (
+                    description,
+                ),
+            )
+
+    def test_all_descriptions_are_unique(self):
+        for group in groups(self.test_files):
+            descriptions = set(test["description"] for test in group["tests"])
+            self.assertEqual(
+                len(descriptions),
+                len(group["tests"]),
+                "%r contains a duplicate description" % (group,)
+            )
+
+    @unittest.skipIf(jsonschema is None, "Validation library not present!")
+    def test_all_schemas_are_valid(self):
+        for schema in os.listdir(SUITE_ROOT_DIR):
+            schema_validator = validators.get(schema)
+            if schema_validator is not None:
+                test_files = collect(os.path.join(SUITE_ROOT_DIR, schema))
+                for case in cases(test_files):
+                    try:
+                        schema_validator.check_schema(case["schema"])
+                    except jsonschema.SchemaError as error:
+                        self.fail("%s contains an invalid schema (%s)" %
+                                  (case, error))
+            else:
+                warnings.warn("No schema validator for %s" % schema)
+
+    @unittest.skipIf(jsonschema is None, "Validation library not present!")
+    def test_suites_are_valid(self):
+        validator = jsonschema.Draft4Validator(TESTSUITE_SCHEMA)
+        for tests in files(self.test_files):
+            try:
+                validator.validate(tests)
+            except jsonschema.ValidationError as error:
+                self.fail(str(error))
+
+    def test_remote_schemas_are_updated(self):
+        files = {}
+        for parent, _, paths in os.walk(REMOTES_DIR):
+            for path in paths:
+                absolute_path = os.path.join(parent, path)
+                with open(absolute_path) as schema_file:
+                    files[absolute_path] = json.load(schema_file)
+
+        expected = {
+            os.path.join(REMOTES_DIR, path): contents
+            for path, contents in REMOTES.items()
+        }
+
+        missing = set(files).symmetric_difference(expected)
+        changed = {
+            path
+            for path, contents in expected.items()
+            if path in files
+            and contents != files[path]
+        }
+
+        self.assertEqual(
+            files,
+            expected,
+            msg=textwrap.dedent(
+                """
+                Remotes in the remotes/ directory do not match those in the
+                ``jsonschema_suite`` Python script.
+
+                Unfortunately for the minute, each remote file is duplicated in
+                two places.""" + ("""
+
+                Only present in one location:
+
+                {}""".format("\n".join(missing)) if missing else "") + ("""
+
+                Conflicting between the two:
+
+                {}""".format("\n".join(changed)) if changed else "")
+            )
+        )
+
+
+def main(arguments):
+    if arguments.command == "check":
+        suite = unittest.TestLoader().loadTestsFromTestCase(SanityTests)
+        result = unittest.TextTestRunner(verbosity=2).run(suite)
+        sys.exit(not result.wasSuccessful())
+    elif arguments.command == "flatten":
+        selected_cases = [case for case in cases(collect(arguments.version))]
+
+        if arguments.randomize:
+            random.shuffle(selected_cases)
+
+        json.dump(selected_cases, sys.stdout, indent=4, sort_keys=True)
+    elif arguments.command == "remotes":
+        json.dump(REMOTES, sys.stdout, indent=4, sort_keys=True)
+    elif arguments.command == "dump_remotes":
+        if arguments.update:
+            shutil.rmtree(arguments.out_dir, ignore_errors=True)
+
+        try:
+            os.makedirs(arguments.out_dir)
+        except OSError as e:
+            if e.errno == errno.EEXIST:
+                print("%s already exists. Aborting." % arguments.out_dir)
+                sys.exit(1)
+            raise
+
+        for url, schema in REMOTES.items():
+            filepath = os.path.join(arguments.out_dir, url)
+
+            try:
+                os.makedirs(os.path.dirname(filepath))
+            except OSError as e:
+                if e.errno != errno.EEXIST:
+                    raise
+
+            with open(filepath, "w") as out_file:
+                json.dump(schema, out_file, indent=4, sort_keys=True)
+                out_file.write("\n")
+    elif arguments.command == "serve":
+        try:
+            from flask import Flask, jsonify
+        except ImportError:
+            print(textwrap.dedent("""
+                The Flask library is required to serve the remote schemas.
+
+                You can install it by running `pip install Flask`.
+
+                Alternatively, see the `jsonschema_suite remotes` or
+                `jsonschema_suite dump_remotes` commands to create static files
+                that can be served with your own web server.
+            """.strip("\n")))
+            sys.exit(1)
+
+        app = Flask(__name__)
+
+        @app.route("/<path:path>")
+        def serve_path(path):
+            if path in REMOTES:
+                return jsonify(REMOTES[path])
+            return "Document does not exist.", 404
+
+        app.run(port=1234)
+
+
+parser = argparse.ArgumentParser(
+    description="JSON Schema Test Suite utilities",
+)
+subparsers = parser.add_subparsers(help="utility commands", dest="command")
+
+check = subparsers.add_parser("check", help="Sanity check the test suite.")
+
+flatten = subparsers.add_parser(
+    "flatten",
+    help="Output a flattened file containing a selected version's test cases."
+)
+flatten.add_argument(
+    "--randomize",
+    action="store_true",
+    help="Randomize the order of the outputted cases.",
+)
+flatten.add_argument(
+    "version", help="The directory containing the version to output",
+)
+
+remotes = subparsers.add_parser(
+    "remotes",
+    help="Output the expected URLs and their associated schemas for remote "
+         "ref tests as a JSON object."
+)
+
+dump_remotes = subparsers.add_parser(
+    "dump_remotes", help="Dump the remote ref schemas into a file tree",
+)
+dump_remotes.add_argument(
+    "--update",
+    action="store_true",
+    help="Update the remotes in an existing directory.",
+)
+dump_remotes.add_argument(
+    "--out-dir",
+    default=REMOTES_DIR,
+    type=os.path.abspath,
+    help="The output directory to create as the root of the file tree",
+)
+
+serve = subparsers.add_parser(
+    "serve",
+    help="Start a webserver to serve schemas used by remote ref tests."
+)
+
+if __name__ == "__main__":
+    main(parser.parse_args())
diff --git a/JSON-Schema-Test-Suite/index.js b/JSON-Schema-Test-Suite/index.js
new file mode 100644
index 0000000..b138226
--- /dev/null
+++ b/JSON-Schema-Test-Suite/index.js
@@ -0,0 +1,45 @@
+'use strict';
+
+const Ajv = require('ajv');
+const jsonSchemaTest = require('json-schema-test');
+const assert = require('assert');
+
+const refs = {
+  'http://localhost:1234/integer.json': require('./remotes/integer.json'),
+  'http://localhost:1234/subSchemas.json': require('./remotes/subSchemas.json'),
+  'http://localhost:1234/folder/folderInteger.json': require('./remotes/folder/folderInteger.json'),
+  'http://localhost:1234/name.json': require('./remotes/name.json'),
+  'http://localhost:1234/name-defs.json': require('./remotes/name-defs.json')
+};
+
+const SKIP = {
+  4: ['optional/zeroTerminatedFloats'],
+  7: [
+    'format/idn-email',
+    'format/idn-hostname',
+    'format/iri',
+    'format/iri-reference',
+    'optional/content'
+  ]
+};
+
+[4, 6, 7].forEach((draft) => {
+  let ajv;
+  if (draft == 7) {
+    ajv = new Ajv({format: 'full'});
+  } else {
+    const schemaId = draft == 4 ? 'id' : '$id';
+    ajv = new Ajv({format: 'full', meta: false, schemaId});
+    ajv.addMetaSchema(require(`ajv/lib/refs/json-schema-draft-0${draft}.json`));
+    ajv._opts.defaultMeta = `http://json-schema.org/draft-0${draft}/schema#`;
+  }
+  for (const uri in refs) ajv.addSchema(refs[uri], uri);
+
+  jsonSchemaTest(ajv, {
+    description: `Test suite draft-0${draft}`,
+    suites: {tests: `./tests/draft${draft}/{**/,}*.json`},
+    skip: SKIP[draft],
+    cwd: __dirname,
+    hideFolder: 'tests/'
+  });
+});
diff --git a/JSON-Schema-Test-Suite/package.json b/JSON-Schema-Test-Suite/package.json
new file mode 100644
index 0000000..3980136
--- /dev/null
+++ b/JSON-Schema-Test-Suite/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "json-schema-test-suite",
+  "version": "0.1.0",
+  "description": "A language agnostic test suite for the JSON Schema specifications",
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha index.js -R spec"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/json-schema-org/JSON-Schema-Test-Suite.git"
+  },
+  "keywords": [
+    "json-schema",
+    "tests"
+  ],
+  "author": "http://json-schema.org",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/json-schema-org/JSON-Schema-Test-Suite/issues"
+  },
+  "homepage": "https://github.com/json-schema-org/JSON-Schema-Test-Suite#readme",
+  "devDependencies": {
+    "ajv": "^6.0.0-rc.1",
+    "json-schema-test": "^2.0.0",
+    "mocha": "^3.2.0"
+  }
+}
diff --git a/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json b/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json
new file mode 100644
index 0000000..8b50ea3
--- /dev/null
+++ b/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json
@@ -0,0 +1,3 @@
+{
+    "type": "integer"
+}
diff --git a/JSON-Schema-Test-Suite/remotes/integer.json b/JSON-Schema-Test-Suite/remotes/integer.json
new file mode 100644
index 0000000..8b50ea3
--- /dev/null
+++ b/JSON-Schema-Test-Suite/remotes/integer.json
@@ -0,0 +1,3 @@
+{
+    "type": "integer"
+}
diff --git a/JSON-Schema-Test-Suite/remotes/name-defs.json b/JSON-Schema-Test-Suite/remotes/name-defs.json
new file mode 100644
index 0000000..1dab4a4
--- /dev/null
+++ b/JSON-Schema-Test-Suite/remotes/name-defs.json
@@ -0,0 +1,15 @@
+{
+    "$defs": {
+        "orNull": {
+            "anyOf": [
+                {
+                    "type": "null"
+                },
+                {
+                    "$ref": "#"
+                }
+            ]
+        }
+    },
+    "type": "string"
+}
diff --git a/JSON-Schema-Test-Suite/remotes/name.json b/JSON-Schema-Test-Suite/remotes/name.json
new file mode 100644
index 0000000..fceacb8
--- /dev/null
+++ b/JSON-Schema-Test-Suite/remotes/name.json
@@ -0,0 +1,15 @@
+{
+    "definitions": {
+        "orNull": {
+            "anyOf": [
+                {
+                    "type": "null"
+                },
+                {
+                    "$ref": "#"
+                }
+            ]
+        }
+    },
+    "type": "string"
+}
diff --git a/JSON-Schema-Test-Suite/remotes/subSchemas.json b/JSON-Schema-Test-Suite/remotes/subSchemas.json
new file mode 100644
index 0000000..9f8030b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/remotes/subSchemas.json
@@ -0,0 +1,8 @@
+{
+    "integer": {
+        "type": "integer"
+    },
+    "refToInteger": {
+        "$ref": "#/integer"
+    }
+}
diff --git a/JSON-Schema-Test-Suite/test-schema.json b/JSON-Schema-Test-Suite/test-schema.json
new file mode 100644
index 0000000..670d280
--- /dev/null
+++ b/JSON-Schema-Test-Suite/test-schema.json
@@ -0,0 +1,59 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "definitions": {
+        "outputItem": {
+            "type": "object",
+            "properties": {
+                "valid": {"type": "boolean"},
+                "keywordLocation": {"type": "string"},
+                "absoluteKeywordLocation": {
+                    "type": "string",
+                    "format": "uri"
+                },
+                "instanceLocation": {"type": "string"},
+                "annotations": {
+                    "type": "array",
+                    "items": {"$ref": "#/definitions/outputItem"}
+                },
+                "errors": {
+                    "type": "array",
+                    "items": {"$ref": "#/definitions/outputItem"}
+                }
+            }
+        }
+    },
+    "type": "array",
+    "items": {
+        "type": "object",
+        "required": ["description", "schema", "tests"],
+        "properties": {
+            "description": {"type": "string"},
+            "schema": {},
+            "tests": {
+                "type": "array",
+                "items": {
+                    "type": "object",
+                    "required": ["description", "data", "valid"],
+                    "properties": {
+                        "description": {"type": "string"},
+                        "data": {},
+                        "valid": {"type": "boolean"},
+                        "output": {
+                            "type": "object",
+                            "properties": {
+                                "basic": {"$ref": "#/definitions/outputItem"},
+                                "detailed": {"$ref": "#/definitions/outputItem"},
+                                "verbose": {"$ref": "#/definitions/outputItem"}
+                            },
+                            "required": ["basic", "detailed", "verbose"]
+                        }
+                    },
+                    "additionalProperties": false
+                },
+                "minItems": 1
+            }
+        },
+        "additionalProperties": false,
+        "minItems": 1
+    }
+}
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/additionalItems.json b/JSON-Schema-Test-Suite/tests/draft2019-09/additionalItems.json
new file mode 100644
index 0000000..abecc57
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/additionalItems.json
@@ -0,0 +1,87 @@
+[
+    {
+        "description": "additionalItems as schema",
+        "schema": {
+            "items": [{}],
+            "additionalItems": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "additional items match schema",
+                "data": [ null, 2, 3, 4 ],
+                "valid": true
+            },
+            {
+                "description": "additional items do not match schema",
+                "data": [ null, 2, 3, "foo" ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "items is schema, no additionalItems",
+        "schema": {
+            "items": {},
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "all items match schema",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "array of items with no additionalItems",
+        "schema": {
+            "items": [{}, {}, {}],
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "fewer number of items present",
+                "data": [ 1, 2 ],
+                "valid": true
+            },
+            {
+                "description": "equal number of items present",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "additional items are not permitted",
+                "data": [ 1, 2, 3, 4 ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalItems as false without items",
+        "schema": {"additionalItems": false},
+        "tests": [
+            {
+                "description":
+                    "items defaults to empty schema so everything is valid",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalItems are allowed by default",
+        "schema": {"items": [{"type": "integer"}]},
+        "tests": [
+            {
+                "description": "only the first item is validated",
+                "data": [1, "foo", false],
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/additionalProperties.json b/JSON-Schema-Test-Suite/tests/draft2019-09/additionalProperties.json
new file mode 100644
index 0000000..ffeac6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/additionalProperties.json
@@ -0,0 +1,133 @@
+[
+    {
+        "description":
+            "additionalProperties being false does not allow other properties",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "patternProperties": { "^v": {} },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobarbaz",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "patternProperties are not additional properties",
+                "data": {"foo":1, "vroom": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "non-ASCII pattern with additionalProperties",
+        "schema": {
+            "patternProperties": {"^á": {}},
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "matching the pattern is valid",
+                "data": {"ármányos": 2},
+                "valid": true
+            },
+            {
+                "description": "not matching the pattern is invalid",
+                "data": {"élmény": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties allows a schema which should validate",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : 12},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties can exist by itself",
+        "schema": {
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties are allowed by default",
+        "schema": {"properties": {"foo": {}, "bar": {}}},
+        "tests": [
+            {
+                "description": "additional properties are allowed",
+                "data": {"foo": 1, "bar": 2, "quux": true},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties should not look in applicators",
+        "schema": {
+            "allOf": [
+                {"properties": {"foo": {}}}
+            ],
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "properties defined in allOf are not allowed",
+                "data": {"foo": 1, "bar": true},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/allOf.json b/JSON-Schema-Test-Suite/tests/draft2019-09/allOf.json
new file mode 100644
index 0000000..eb61209
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/allOf.json
@@ -0,0 +1,218 @@
+[
+    {
+        "description": "allOf",
+        "schema": {
+            "allOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "allOf",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "mismatch second",
+                "data": {"foo": "baz"},
+                "valid": false
+            },
+            {
+                "description": "mismatch first",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "baz", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with base schema",
+        "schema": {
+            "properties": {"bar": {"type": "integer"}},
+            "required": ["bar"],
+            "allOf" : [
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                },
+                {
+                    "properties": {
+                        "baz": {"type": "null"}
+                    },
+                    "required": ["baz"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": "quux", "bar": 2, "baz": null},
+                "valid": true
+            },
+            {
+                "description": "mismatch base schema",
+                "data": {"foo": "quux", "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch first allOf",
+                "data": {"bar": 2, "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch second allOf",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "mismatch both",
+                "data": {"bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf simple types",
+        "schema": {
+            "allOf": [
+                {"maximum": 30},
+                {"minimum": 20}
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": 25,
+                "valid": true
+            },
+            {
+                "description": "mismatch one",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, all true",
+        "schema": {"allOf": [true, true]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, some false",
+        "schema": {"allOf": [true, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, all false",
+        "schema": {"allOf": [false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with one empty schema",
+        "schema": {
+            "allOf": [
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with two empty schemas",
+        "schema": {
+            "allOf": [
+                {},
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with the first empty schema",
+        "schema": {
+            "allOf": [
+                {},
+                { "type": "number" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with the last empty schema",
+        "schema": {
+            "allOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/anchor.json b/JSON-Schema-Test-Suite/tests/draft2019-09/anchor.json
new file mode 100644
index 0000000..06b0ba4
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/anchor.json
@@ -0,0 +1,87 @@
+[
+    {
+        "description": "Location-independent identifier",
+        "schema": {
+            "allOf": [{
+                "$ref": "#foo"
+            }],
+            "$defs": {
+                "A": {
+                    "$anchor": "foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with absolute URI",
+        "schema": {
+            "allOf": [{
+                "$ref": "http://localhost:1234/bar#foo"
+            }],
+            "$defs": {
+                "A": {
+                    "$id": "http://localhost:1234/bar",
+                    "$anchor": "foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with base URI change in subschema",
+        "schema": {
+            "$id": "http://localhost:1234/root",
+            "allOf": [{
+                "$ref": "http://localhost:1234/nested.json#foo"
+            }],
+            "$defs": {
+                "A": {
+                    "$id": "nested.json",
+                    "$defs": {
+                        "B": {
+                            "$anchor": "foo",
+                            "type": "integer"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/anyOf.json b/JSON-Schema-Test-Suite/tests/draft2019-09/anyOf.json
new file mode 100644
index 0000000..ab5eb38
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/anyOf.json
@@ -0,0 +1,189 @@
+[
+    {
+        "description": "anyOf",
+        "schema": {
+            "anyOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid",
+                "data": 3,
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with base schema",
+        "schema": {
+            "type": "string",
+            "anyOf" : [
+                {
+                    "maxLength": 2
+                },
+                {
+                    "minLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one anyOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both anyOf invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, all true",
+        "schema": {"anyOf": [true, true]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, some true",
+        "schema": {"anyOf": [true, false]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, all false",
+        "schema": {"anyOf": [false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf complex types",
+        "schema": {
+            "anyOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with one empty schema",
+        "schema": {
+            "anyOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is valid",
+                "data": 123,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested anyOf, to check validation semantics",
+        "schema": {
+            "anyOf": [
+                {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        }
+                    ]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "anything non-null is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/boolean_schema.json b/JSON-Schema-Test-Suite/tests/draft2019-09/boolean_schema.json
new file mode 100644
index 0000000..6d40f23
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/boolean_schema.json
@@ -0,0 +1,104 @@
+[
+    {
+        "description": "boolean schema 'true'",
+        "schema": true,
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "boolean true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "boolean false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": "bar"},
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "array is valid",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "boolean schema 'false'",
+        "schema": false,
+        "tests": [
+            {
+                "description": "number is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "boolean true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "boolean false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "object is invalid",
+                "data": {"foo": "bar"},
+                "valid": false
+            },
+            {
+                "description": "empty object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "array is invalid",
+                "data": ["foo"],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/const.json b/JSON-Schema-Test-Suite/tests/draft2019-09/const.json
new file mode 100644
index 0000000..c089625
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/const.json
@@ -0,0 +1,170 @@
+[
+    {
+        "description": "const validation",
+        "schema": {"const": 2},
+        "tests": [
+            {
+                "description": "same value is valid",
+                "data": 2,
+                "valid": true
+            },
+            {
+                "description": "another value is invalid",
+                "data": 5,
+                "valid": false
+            },
+            {
+                "description": "another type is invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with object",
+        "schema": {"const": {"foo": "bar", "baz": "bax"}},
+        "tests": [
+            {
+                "description": "same object is valid",
+                "data": {"foo": "bar", "baz": "bax"},
+                "valid": true
+            },
+            {
+                "description": "same object with different property order is valid",
+                "data": {"baz": "bax", "foo": "bar"},
+                "valid": true
+            },
+            {
+                "description": "another object is invalid",
+                "data": {"foo": "bar"},
+                "valid": false
+            },
+            {
+                "description": "another type is invalid",
+                "data": [1, 2],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with array",
+        "schema": {"const": [{ "foo": "bar" }]},
+        "tests": [
+            {
+                "description": "same array is valid",
+                "data": [{"foo": "bar"}],
+                "valid": true
+            },
+            {
+                "description": "another array item is invalid",
+                "data": [2],
+                "valid": false
+            },
+            {
+                "description": "array with additional items is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with null",
+        "schema": {"const": null},
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "not null is invalid",
+                "data": 0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with false does not match 0",
+        "schema": {"const": false},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with true does not match 1",
+        "schema": {"const": true},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with 0 does not match false",
+        "schema": {"const": 0},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "const with 1 does not match true",
+        "schema": {"const": 1},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/contains.json b/JSON-Schema-Test-Suite/tests/draft2019-09/contains.json
new file mode 100644
index 0000000..b7ae5a2
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/contains.json
@@ -0,0 +1,95 @@
+[
+    {
+        "description": "contains keyword validation",
+        "schema": {
+            "contains": {"minimum": 5}
+        },
+        "tests": [
+            {
+                "description": "array with item matching schema (5) is valid",
+                "data": [3, 4, 5],
+                "valid": true
+            },
+            {
+                "description": "array with item matching schema (6) is valid",
+                "data": [3, 4, 6],
+                "valid": true
+            },
+            {
+                "description": "array with two items matching schema (5, 6) is valid",
+                "data": [3, 4, 5, 6],
+                "valid": true
+            },
+            {
+                "description": "array without items matching schema is invalid",
+                "data": [2, 3, 4],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "not array is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with const keyword",
+        "schema": {
+            "contains": { "const": 5 }
+        },
+        "tests": [
+            {
+                "description": "array with item 5 is valid",
+                "data": [3, 4, 5],
+                "valid": true
+            },
+            {
+                "description": "array with two items 5 is valid",
+                "data": [3, 4, 5, 5],
+                "valid": true
+            },
+            {
+                "description": "array without item 5 is invalid",
+                "data": [1, 2, 3, 4],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with boolean schema true",
+        "schema": {"contains": true},
+        "tests": [
+            {
+                "description": "any non-empty array is valid",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with boolean schema false",
+        "schema": {"contains": false},
+        "tests": [
+            {
+                "description": "any non-empty array is invalid",
+                "data": ["foo"],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/default.json b/JSON-Schema-Test-Suite/tests/draft2019-09/default.json
new file mode 100644
index 0000000..1762977
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/default.json
@@ -0,0 +1,49 @@
+[
+    {
+        "description": "invalid type for default",
+        "schema": {
+            "properties": {
+                "foo": {
+                    "type": "integer",
+                    "default": []
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"foo": 13},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid string value for default",
+        "schema": {
+            "properties": {
+                "bar": {
+                    "type": "string",
+                    "minLength": 4,
+                    "default": "bad"
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"bar": "good"},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/defs.json b/JSON-Schema-Test-Suite/tests/draft2019-09/defs.json
new file mode 100644
index 0000000..f2fbec4
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/defs.json
@@ -0,0 +1,24 @@
+[
+    {
+        "description": "valid definition",
+        "schema": {"$ref": "https://json-schema.org/draft/2019-09/schema"},
+        "tests": [
+            {
+                "description": "valid definition schema",
+                "data": {"$defs": {"foo": {"type": "integer"}}},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid definition",
+        "schema": {"$ref": "https://json-schema.org/draft/2019-09/schema"},
+        "tests": [
+            {
+                "description": "invalid definition schema",
+                "data": {"$defs": {"foo": {"type": 1}}},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/dependencies.json b/JSON-Schema-Test-Suite/tests/draft2019-09/dependencies.json
new file mode 100644
index 0000000..8dd78aa
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/dependencies.json
@@ -0,0 +1,268 @@
+[
+    {
+        "description": "dependencies",
+        "schema": {
+            "dependencies": {"bar": ["foo"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependant",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "with dependency",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["bar"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "dependencies with empty array",
+        "schema": {
+            "dependencies": {"bar": []}
+        },
+        "tests": [
+            {
+                "description": "empty object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "object with one property",
+                "data": {"bar": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies",
+        "schema": {
+            "dependencies": {"quux": ["foo", "bar"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependants",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "with dependencies",
+                "data": {"foo": 1, "bar": 2, "quux": 3},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"foo": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing other dependency",
+                "data": {"bar": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing both dependencies",
+                "data": {"quux": 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies subschema",
+        "schema": {
+            "dependencies": {
+                "bar": {
+                    "properties": {
+                        "foo": {"type": "integer"},
+                        "bar": {"type": "integer"}
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "no dependency",
+                "data": {"foo": "quux"},
+                "valid": true
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type other",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            },
+            {
+                "description": "wrong type both",
+                "data": {"foo": "quux", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "dependencies with boolean subschemas",
+        "schema": {
+            "dependencies": {
+                "foo": true,
+                "bar": false
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property having schema true is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "object with property having schema false is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "object with both properties is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "empty array of dependencies",
+        "schema": {
+            "dependencies": {
+                "foo": []
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property is valid",
+                "data": { "foo": 1 },
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "non-object is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "dependencies with escaped characters",
+        "schema": {
+            "dependencies": {
+                "foo\nbar": ["foo\rbar"],
+                "foo\tbar": {
+                    "minProperties": 4
+                },
+                "foo'bar": {"required": ["foo\"bar"]},
+                "foo\"bar": ["foo'bar"]
+            }
+        },
+        "tests": [
+            {
+                "description": "valid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\rbar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2,
+                    "b": 3,
+                    "c": 4
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 3",
+                "data": {
+                    "foo'bar": 1,
+                    "foo\"bar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 3",
+                "data": {
+                    "foo'bar": 1
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 4",
+                "data": {
+                    "foo\"bar": 2
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/enum.json b/JSON-Schema-Test-Suite/tests/draft2019-09/enum.json
new file mode 100644
index 0000000..32d7902
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/enum.json
@@ -0,0 +1,179 @@
+[
+    {
+        "description": "simple enum validation",
+        "schema": {"enum": [1, 2, 3]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": 4,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "heterogeneous enum validation",
+        "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "objects are deep compared",
+                "data": {"foo": false},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enums in properties",
+        "schema": {
+            "type":"object",
+            "properties": {
+                "foo": {"enum":["foo"]},
+                "bar": {"enum":["bar"]}
+            },
+            "required": ["bar"]
+        },
+        "tests": [
+            {
+                "description": "both properties are valid",
+                "data": {"foo":"foo", "bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing optional property is valid",
+                "data": {"bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing required property is invalid",
+                "data": {"foo":"foo"},
+                "valid": false
+            },
+            {
+                "description": "missing all properties is invalid",
+                "data": {},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with escaped characters",
+        "schema": {
+            "enum": ["foo\nbar", "foo\rbar"]
+        },
+        "tests": [
+            {
+                "description": "member 1 is valid",
+                "data": "foo\nbar",
+                "valid": true
+            },
+            {
+                "description": "member 2 is valid",
+                "data": "foo\rbar",
+                "valid": true
+            },
+            {
+                "description": "another string is invalid",
+                "data": "abc",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with false does not match 0",
+        "schema": {"enum": [false]},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with true does not match 1",
+        "schema": {"enum": [true]},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with 0 does not match false",
+        "schema": {"enum": [0]},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "enum with 1 does not match true",
+        "schema": {"enum": [1]},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/exclusiveMaximum.json b/JSON-Schema-Test-Suite/tests/draft2019-09/exclusiveMaximum.json
new file mode 100644
index 0000000..dc3cd70
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/exclusiveMaximum.json
@@ -0,0 +1,30 @@
+[
+    {
+        "description": "exclusiveMaximum validation",
+        "schema": {
+            "exclusiveMaximum": 3.0
+        },
+        "tests": [
+            {
+                "description": "below the exclusiveMaximum is valid",
+                "data": 2.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 3.0,
+                "valid": false
+            },
+            {
+                "description": "above the exclusiveMaximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/exclusiveMinimum.json b/JSON-Schema-Test-Suite/tests/draft2019-09/exclusiveMinimum.json
new file mode 100644
index 0000000..b38d7ec
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/exclusiveMinimum.json
@@ -0,0 +1,30 @@
+[
+    {
+        "description": "exclusiveMinimum validation",
+        "schema": {
+            "exclusiveMinimum": 1.1
+        },
+        "tests": [
+            {
+                "description": "above the exclusiveMinimum is valid",
+                "data": 1.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "below the exclusiveMinimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/format.json b/JSON-Schema-Test-Suite/tests/draft2019-09/format.json
new file mode 100644
index 0000000..93305f5
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/format.json
@@ -0,0 +1,614 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IDN e-mail addresses",
+        "schema": {"format": "idn-email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of regexes",
+        "schema": {"format": "regex"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IDN hostnames",
+        "schema": {"format": "idn-hostname"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of hostnames",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date strings",
+        "schema": {"format": "date"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of time strings",
+        "schema": {"format": "time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of JSON pointers",
+        "schema": {"format": "json-pointer"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of relative JSON pointers",
+        "schema": {"format": "relative-json-pointer"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IRIs",
+        "schema": {"format": "iri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IRI references",
+        "schema": {"format": "iri-reference"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URI references",
+        "schema": {"format": "uri-reference"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URI templates",
+        "schema": {"format": "uri-template"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/if-then-else.json b/JSON-Schema-Test-Suite/tests/draft2019-09/if-then-else.json
new file mode 100644
index 0000000..be73281
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/if-then-else.json
@@ -0,0 +1,188 @@
+[
+    {
+        "description": "ignore if without then or else",
+        "schema": {
+            "if": {
+                "const": 0
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when valid against lone if",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "valid when invalid against lone if",
+                "data": "hello",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ignore then without if",
+        "schema": {
+            "then": {
+                "const": 0
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when valid against lone then",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "valid when invalid against lone then",
+                "data": "hello",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ignore else without if",
+        "schema": {
+            "else": {
+                "const": 0
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when valid against lone else",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "valid when invalid against lone else",
+                "data": "hello",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "if and then without else",
+        "schema": {
+            "if": {
+                "exclusiveMaximum": 0
+            },
+            "then": {
+                "minimum": -10
+            }
+        },
+        "tests": [
+            {
+                "description": "valid through then",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "invalid through then",
+                "data": -100,
+                "valid": false
+            },
+            {
+                "description": "valid when if test fails",
+                "data": 3,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "if and else without then",
+        "schema": {
+            "if": {
+                "exclusiveMaximum": 0
+            },
+            "else": {
+                "multipleOf": 2
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when if test passes",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "valid through else",
+                "data": 4,
+                "valid": true
+            },
+            {
+                "description": "invalid through else",
+                "data": 3,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validate against correct branch, then vs else",
+        "schema": {
+            "if": {
+                "exclusiveMaximum": 0
+            },
+            "then": {
+                "minimum": -10
+            },
+            "else": {
+                "multipleOf": 2
+            }
+        },
+        "tests": [
+            {
+                "description": "valid through then",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "invalid through then",
+                "data": -100,
+                "valid": false
+            },
+            {
+                "description": "valid through else",
+                "data": 4,
+                "valid": true
+            },
+            {
+                "description": "invalid through else",
+                "data": 3,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "non-interference across combined schemas",
+        "schema": {
+            "allOf": [
+                {
+                    "if": {
+                        "exclusiveMaximum": 0
+                    }
+                },
+                {
+                    "then": {
+                        "minimum": -10
+                    }
+                },
+                {
+                    "else": {
+                        "multipleOf": 2
+                    }
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid, but would have been invalid through then",
+                "data": -100,
+                "valid": true
+            },
+            {
+                "description": "valid, but would have been invalid through else",
+                "data": 3,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/items.json b/JSON-Schema-Test-Suite/tests/draft2019-09/items.json
new file mode 100644
index 0000000..6e98ee8
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/items.json
@@ -0,0 +1,250 @@
+[
+    {
+        "description": "a schema given for items",
+        "schema": {
+            "items": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "wrong type of items",
+                "data": [1, "x"],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "length": 1
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "an array of schemas for items",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"type": "string"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "correct types",
+                "data": [ 1, "foo" ],
+                "valid": true
+            },
+            {
+                "description": "wrong types",
+                "data": [ "foo", 1 ],
+                "valid": false
+            },
+            {
+                "description": "incomplete array of items",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with additional items",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array",
+                "data": [ ],
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "1": "valid",
+                    "length": 2
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schema (true)",
+        "schema": {"items": true},
+        "tests": [
+            {
+                "description": "any array is valid",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schema (false)",
+        "schema": {"items": false},
+        "tests": [
+            {
+                "description": "any non-empty array is invalid",
+                "data": [ 1, "foo", true ],
+                "valid": false
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schemas",
+        "schema": {
+            "items": [true, false]
+        },
+        "tests": [
+            {
+                "description": "array with one item is valid",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with two items is invalid",
+                "data": [ 1, "foo" ],
+                "valid": false
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items and subitems",
+        "schema": {
+            "$defs": {
+                "item": {
+                    "type": "array",
+                    "additionalItems": false,
+                    "items": [
+                        { "$ref": "#/$defs/sub-item" },
+                        { "$ref": "#/$defs/sub-item" }
+                    ]
+                },
+                "sub-item": {
+                    "type": "object",
+                    "required": ["foo"]
+                }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+                { "$ref": "#/$defs/item" },
+                { "$ref": "#/$defs/item" },
+                { "$ref": "#/$defs/item" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": true
+            },
+            {
+                "description": "too many items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "too many sub-items",
+                "data": [
+                    [ {"foo": null}, {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong item",
+                "data": [
+                    {"foo": null},
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong sub-item",
+                "data": [
+                    [ {}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "fewer items is valid",
+                "data": [
+                    [ {"foo": null} ],
+                    [ {"foo": null} ]
+                ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested items",
+        "schema": {
+            "type": "array",
+            "items": {
+                "type": "array",
+                "items": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {
+                            "type": "number"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid nested array",
+                "data": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": true
+            },
+            {
+                "description": "nested array with invalid type",
+                "data": [[[["1"]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": false
+            },
+            {
+                "description": "not deep enough",
+                "data": [[[1], [2],[3]], [[4], [5], [6]]],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/maxItems.json b/JSON-Schema-Test-Suite/tests/draft2019-09/maxItems.json
new file mode 100644
index 0000000..3b53a6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/maxItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maxItems validation",
+        "schema": {"maxItems": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "foobar",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/maxLength.json b/JSON-Schema-Test-Suite/tests/draft2019-09/maxLength.json
new file mode 100644
index 0000000..811d35b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/maxLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "maxLength validation",
+        "schema": {"maxLength": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": "f",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            },
+            {
+                "description": "two supplementary Unicode code points is long enough",
+                "data": "\uD83D\uDCA9\uD83D\uDCA9",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/maxProperties.json b/JSON-Schema-Test-Suite/tests/draft2019-09/maxProperties.json
new file mode 100644
index 0000000..513731e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/maxProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "maxProperties validation",
+        "schema": {"maxProperties": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": {"foo": 1, "bar": 2, "baz": 3},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/maximum.json b/JSON-Schema-Test-Suite/tests/draft2019-09/maximum.json
new file mode 100644
index 0000000..8150984
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/maximum.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maximum validation",
+        "schema": {"maximum": 3.0},
+        "tests": [
+            {
+                "description": "below the maximum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 3.0,
+                "valid": true
+            },
+            {
+                "description": "above the maximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/minItems.json b/JSON-Schema-Test-Suite/tests/draft2019-09/minItems.json
new file mode 100644
index 0000000..ed51188
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/minItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "minItems validation",
+        "schema": {"minItems": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/minLength.json b/JSON-Schema-Test-Suite/tests/draft2019-09/minLength.json
new file mode 100644
index 0000000..3f09158
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/minLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "minLength validation",
+        "schema": {"minLength": 2},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": "f",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "one supplementary Unicode code point is not long enough",
+                "data": "\uD83D\uDCA9",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/minProperties.json b/JSON-Schema-Test-Suite/tests/draft2019-09/minProperties.json
new file mode 100644
index 0000000..49a0726
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/minProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "minProperties validation",
+        "schema": {"minProperties": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/minimum.json b/JSON-Schema-Test-Suite/tests/draft2019-09/minimum.json
new file mode 100644
index 0000000..2a9c42b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/minimum.json
@@ -0,0 +1,59 @@
+[
+    {
+        "description": "minimum validation",
+        "schema": {"minimum": 1.1},
+        "tests": [
+            {
+                "description": "above the minimum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "minimum validation with signed integer",
+        "schema": {"minimum": -2},
+        "tests": [
+            {
+                "description": "negative above the minimum is valid",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "positive above the minimum is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": -2,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": -3,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/multipleOf.json b/JSON-Schema-Test-Suite/tests/draft2019-09/multipleOf.json
new file mode 100644
index 0000000..ca3b761
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/multipleOf.json
@@ -0,0 +1,60 @@
+[
+    {
+        "description": "by int",
+        "schema": {"multipleOf": 2},
+        "tests": [
+            {
+                "description": "int by int",
+                "data": 10,
+                "valid": true
+            },
+            {
+                "description": "int by int fail",
+                "data": 7,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "by number",
+        "schema": {"multipleOf": 1.5},
+        "tests": [
+            {
+                "description": "zero is multiple of anything",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "4.5 is multiple of 1.5",
+                "data": 4.5,
+                "valid": true
+            },
+            {
+                "description": "35 is not multiple of 1.5",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "by small number",
+        "schema": {"multipleOf": 0.0001},
+        "tests": [
+            {
+                "description": "0.0075 is multiple of 0.0001",
+                "data": 0.0075,
+                "valid": true
+            },
+            {
+                "description": "0.00751 is not multiple of 0.0001",
+                "data": 0.00751,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/not.json b/JSON-Schema-Test-Suite/tests/draft2019-09/not.json
new file mode 100644
index 0000000..98de0ed
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/not.json
@@ -0,0 +1,117 @@
+[
+    {
+        "description": "not",
+        "schema": {
+            "not": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "allowed",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "disallowed",
+                "data": 1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not multiple types",
+        "schema": {
+            "not": {"type": ["integer", "boolean"]}
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "other mismatch",
+                "data": true,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not more complex schema",
+        "schema": {
+            "not": {
+                "type": "object",
+                "properties": {
+                    "foo": {
+                        "type": "string"
+                    }
+                }
+             }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "other match",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"foo": "bar"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "forbidden property",
+        "schema": {
+            "properties": {
+                "foo": { 
+                    "not": {}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "property present",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "property absent",
+                "data": {"bar": 1, "baz": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "not with boolean schema true",
+        "schema": {"not": true},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not with boolean schema false",
+        "schema": {"not": false},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/oneOf.json b/JSON-Schema-Test-Suite/tests/draft2019-09/oneOf.json
new file mode 100644
index 0000000..57640b7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/oneOf.json
@@ -0,0 +1,206 @@
+[
+    {
+        "description": "oneOf",
+        "schema": {
+            "oneOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with base schema",
+        "schema": {
+            "type": "string",
+            "oneOf" : [
+                {
+                    "minLength": 2
+                },
+                {
+                    "maxLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one oneOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, all true",
+        "schema": {"oneOf": [true, true, true]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, one true",
+        "schema": {"oneOf": [true, false, false]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, more than one true",
+        "schema": {"oneOf": [true, true, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, all false",
+        "schema": {"oneOf": [false, false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf complex types",
+        "schema": {
+            "oneOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with empty schema",
+        "schema": {
+            "oneOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "one valid - valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with required",
+        "schema": {
+            "type": "object",
+            "oneOf": [
+                { "required": ["foo", "bar"] },
+                { "required": ["foo", "baz"] }
+            ]
+        },
+        "tests": [
+            {
+                "description": "both invalid - invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "first valid - valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second valid - valid",
+                "data": {"foo": 1, "baz": 3},
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": {"foo": 1, "bar": 2, "baz" : 3},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/bignum.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/bignum.json
new file mode 100644
index 0000000..fac275e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/bignum.json
@@ -0,0 +1,105 @@
+[
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a bignum is an integer",
+                "data": 12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a bignum is a number",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a negative bignum is an integer",
+                "data": -12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a negative bignum is a number",
+                "data": -98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "string",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "a bignum is not a string",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"maximum": 18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision",
+        "schema": {
+            "exclusiveMaximum": 972783798187987123879878123.18878137
+        },
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"minimum": -18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision on negative numbers",
+        "schema": {
+            "exclusiveMinimum": -972783798187987123879878123.18878137
+        },
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/content.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/content.json
new file mode 100644
index 0000000..3f5a743
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/content.json
@@ -0,0 +1,77 @@
+[
+    {
+        "description": "validation of string-encoded content based on media type",
+        "schema": {
+            "contentMediaType": "application/json"
+        },
+        "tests": [
+            {
+                "description": "a valid JSON document",
+                "data": "{\"foo\": \"bar\"}",
+                "valid": true
+            },
+            {
+                "description": "an invalid JSON document",
+                "data": "{:}",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of binary string-encoding",
+        "schema": {
+            "contentEncoding": "base64"
+        },
+        "tests": [
+            {
+                "description": "a valid base64 string",
+                "data": "eyJmb28iOiAiYmFyIn0K",
+                "valid": true
+            },
+            {
+                "description": "an invalid base64 string (% is not a valid character)",
+                "data": "eyJmb28iOi%iYmFyIn0K",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of binary-encoded media type documents",
+        "schema": {
+            "contentMediaType": "application/json",
+            "contentEncoding": "base64"
+        },
+        "tests": [
+            {
+                "description": "a valid base64-encoded JSON document",
+                "data": "eyJmb28iOiAiYmFyIn0K",
+                "valid": true
+            },
+            {
+                "description": "a validly-encoded invalid JSON document",
+                "data": "ezp9Cg==",
+                "valid": false
+            },
+            {
+                "description": "an invalid base64 string that is valid JSON",
+                "data": "{}",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/ecmascript-regex.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/ecmascript-regex.json
new file mode 100644
index 0000000..d82e0fe
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/ecmascript-regex.json
@@ -0,0 +1,213 @@
+[
+    {
+        "description": "ECMA 262 regex non-compliance",
+        "schema": { "format": "regex" },
+        "tests": [
+            {
+                "description": "ECMA 262 has no support for \\Z anchor from .NET",
+                "data": "^\\S(|(.|\\n)*\\S)\\Z",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex $ does not match trailing newline",
+        "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+        },
+        "tests": [
+            {
+                "description": "matches in Python, but should not in jsonschema",
+                "data": "abc\n",
+                "valid": false
+            },
+            {
+                "description": "should match",
+                "data": "abc",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex converts \\a to ascii BEL",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\a",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0007",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and upper letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cC",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and lower letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cc",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\d matches ascii digits only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero matches",
+                "data": "0",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO does not match (unlike e.g. Python)",
+                "data": "߀",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) does not match",
+                "data": "\u07c0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\D matches everything but ascii digits",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero does not match",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO matches (unlike e.g. Python)",
+                "data": "߀",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) matches",
+                "data": "\u07c0",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches ascii letters only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' matches",
+                "data": "a",
+                "valid": true
+            },
+            {
+                "description": "latin-1 e-acute does not match (unlike e.g. Python)",
+                "data": "é",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches everything but ascii letters",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' does not match",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "latin-1 e-acute matches (unlike e.g. Python)",
+                "data": "é",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\s matches ascii whitespace only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space matches",
+                "data": " ",
+                "valid": true
+            },
+            {
+                "description": "latin-1 non-breaking-space does not match (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\S matches everything but ascii whitespace",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space does not match",
+                "data": " ",
+                "valid": false
+            },
+            {
+                "description": "latin-1 non-breaking-space matches (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/date-time.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/date-time.json
new file mode 100644
index 0000000..dfccee6
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/date-time.json
@@ -0,0 +1,53 @@
+[
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "a valid date-time string",
+                "data": "1963-06-19T08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string without second fraction",
+                "data": "1963-06-19T08:30:06Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with plus offset",
+                "data": "1937-01-01T12:00:27.87+00:20",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with minus offset",
+                "data": "1990-12-31T15:59:50.123-08:00",
+                "valid": true
+            },
+            {
+                "description": "a invalid day in date-time string",
+                "data": "1990-02-31T15:59:60.123-08:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid offset in date-time string",
+                "data": "1990-12-31T15:59:60-24:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963 08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "case-insensitive T and Z",
+                "data": "1963-06-19t08:30:06.283185z",
+                "valid": true
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350T01:01:01",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/date.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/date.json
new file mode 100644
index 0000000..cd23baa
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/date.json
@@ -0,0 +1,23 @@
+[
+    {
+        "description": "validation of date strings",
+        "schema": {"format": "date"},
+        "tests": [
+            {
+                "description": "a valid date string",
+                "data": "1963-06-19",
+                "valid": true
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963",
+                "valid": false
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/email.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/email.json
new file mode 100644
index 0000000..c837c84
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/email.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "a valid e-mail address",
+                "data": "joe.bloggs@example.com",
+                "valid": true
+            },
+            {
+                "description": "an invalid e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/hostname.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/hostname.json
new file mode 100644
index 0000000..d22e57d
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/hostname.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "validation of host names",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "a valid host name",
+                "data": "www.example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid punycoded IDN hostname",
+                "data": "xn--4gbwdl.xn--wgbh1c",
+                "valid": true
+            },
+            {
+                "description": "a host name starting with an illegal character",
+                "data": "-a-host-name-that-starts-with--",
+                "valid": false
+            },
+            {
+                "description": "a host name containing illegal characters",
+                "data": "not_a_valid_host_name",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/idn-email.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/idn-email.json
new file mode 100644
index 0000000..637409e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/idn-email.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "validation of an internationalized e-mail addresses",
+        "schema": {"format": "idn-email"},
+        "tests": [
+            {
+                "description": "a valid idn e-mail (example@example.test in Hangul)",
+                "data": "실례@실례.테스트",
+                "valid": true
+            },
+            {
+                "description": "an invalid idn e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/idn-hostname.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/idn-hostname.json
new file mode 100644
index 0000000..3291820
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/idn-hostname.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "validation of internationalized host names",
+        "schema": {"format": "idn-hostname"},
+        "tests": [
+            {
+                "description": "a valid host name (example.test in Hangul)",
+                "data": "실례.테스트",
+                "valid": true
+            },
+            {
+                "description": "illegal first char U+302E Hangul single dot tone mark",
+                "data": "〮실례.테스트",
+                "valid": false
+            },
+            {
+                "description": "contains illegal char U+302E Hangul single dot tone mark",
+                "data": "실〮례.테스트",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/ipv4.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/ipv4.json
new file mode 100644
index 0000000..661148a
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/ipv4.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "a valid IP address",
+                "data": "192.168.0.1",
+                "valid": true
+            },
+            {
+                "description": "an IP address with too many components",
+                "data": "127.0.0.0.1",
+                "valid": false
+            },
+            {
+                "description": "an IP address with out-of-range values",
+                "data": "256.256.256.256",
+                "valid": false
+            },
+            {
+                "description": "an IP address without 4 components",
+                "data": "127.0",
+                "valid": false
+            },
+            {
+                "description": "an IP address as an integer",
+                "data": "0x7f000001",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/ipv6.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/ipv6.json
new file mode 100644
index 0000000..f67559b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/ipv6.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "a valid IPv6 address",
+                "data": "::1",
+                "valid": true
+            },
+            {
+                "description": "an IPv6 address with out-of-range values",
+                "data": "12345::",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address with too many components",
+                "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address containing illegal characters",
+                "data": "::laptop",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/iri-reference.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/iri-reference.json
new file mode 100644
index 0000000..1fd779c
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/iri-reference.json
@@ -0,0 +1,43 @@
+[
+    {
+        "description": "validation of IRI References",
+        "schema": {"format": "iri-reference"},
+        "tests": [
+            {
+                "description": "a valid IRI",
+                "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx",
+                "valid": true
+            },
+            {
+                "description": "a valid protocol-relative IRI Reference",
+                "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx",
+                "valid": true
+            },
+            {
+                "description": "a valid relative IRI Reference",
+                "data": "/âππ",
+                "valid": true
+            },
+            {
+                "description": "an invalid IRI Reference",
+                "data": "\\\\WINDOWS\\filëßåré",
+                "valid": false
+            },
+            {
+                "description": "a valid IRI Reference",
+                "data": "âππ",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI fragment",
+                "data": "#ƒrägmênt",
+                "valid": true
+            },
+            {
+                "description": "an invalid IRI fragment",
+                "data": "#ƒräg\\mênt",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/iri.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/iri.json
new file mode 100644
index 0000000..ed54094
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/iri.json
@@ -0,0 +1,53 @@
+[
+    {
+        "description": "validation of IRIs",
+        "schema": {"format": "iri"},
+        "tests": [
+            {
+                "description": "a valid IRI with anchor tag",
+                "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI with anchor tag and parantheses",
+                "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI with URL-encoded stuff",
+                "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI with many special characters",
+                "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI based on IPv6",
+                "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]",
+                "valid": true
+            },
+            {
+                "description": "an invalid IRI based on IPv6",
+                "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+                "valid": false
+            },
+            {
+                "description": "an invalid relative IRI Reference",
+                "data": "/abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid IRI",
+                "data": "\\\\WINDOWS\\filëßåré",
+                "valid": false
+            },
+            {
+                "description": "an invalid IRI though valid IRI reference",
+                "data": "âππ",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/json-pointer.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/json-pointer.json
new file mode 100644
index 0000000..65c2f06
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/json-pointer.json
@@ -0,0 +1,168 @@
+[
+    {
+        "description": "validation of JSON-pointers (JSON String Representation)",
+        "schema": {"format": "json-pointer"},
+        "tests": [
+            {
+                "description": "a valid JSON-pointer",
+                "data": "/foo/bar~0/baz~1/%a",
+                "valid": true
+            },
+            {
+                "description": "not a valid JSON-pointer (~ not escaped)",
+                "data": "/foo/bar~",
+                "valid": false
+            },
+            {
+                "description": "valid JSON-pointer with empty segment",
+                "data": "/foo//bar",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer with the last empty segment",
+                "data": "/foo/bar/",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #1",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #2",
+                "data": "/foo",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #3",
+                "data": "/foo/0",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #4",
+                "data": "/",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #5",
+                "data": "/a~1b",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #6",
+                "data": "/c%d",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #7",
+                "data": "/e^f",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #8",
+                "data": "/g|h",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #9",
+                "data": "/i\\j",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #10",
+                "data": "/k\"l",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #11",
+                "data": "/ ",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #12",
+                "data": "/m~0n",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer used adding to the last array position",
+                "data": "/foo/-",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (- used as object member name)",
+                "data": "/foo/-/bar",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (multiple escaped characters)",
+                "data": "/~1~0~0~1~1",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (escaped with fraction part) #1",
+                "data": "/~1.1",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (escaped with fraction part) #2",
+                "data": "/~0.1",
+                "valid": true
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #1",
+                "data": "#",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #2",
+                "data": "#/",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #3",
+                "data": "#a",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (some escaped, but not all) #1",
+                "data": "/~0~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (some escaped, but not all) #2",
+                "data": "/~0/~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (wrong escape character) #1",
+                "data": "/~2",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (wrong escape character) #2",
+                "data": "/~-1",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (multiple characters not escaped)",
+                "data": "/~~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3",
+                "data": "a/a",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/regex.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/regex.json
new file mode 100644
index 0000000..d99d021
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/regex.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "validation of regular expressions",
+        "schema": {"format": "regex"},
+        "tests": [
+            {
+                "description": "a valid regular expression",
+                "data": "([abc])+\\s+$",
+                "valid": true
+            },
+            {
+                "description": "a regular expression with unclosed parens is invalid",
+                "data": "^(abc]",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/relative-json-pointer.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/relative-json-pointer.json
new file mode 100644
index 0000000..ceeb743
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/relative-json-pointer.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "validation of Relative JSON Pointers (RJP)",
+        "schema": {"format": "relative-json-pointer"},
+        "tests": [
+            {
+                "description": "a valid upwards RJP",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "a valid downwards RJP",  
+                "data": "0/foo/bar",
+                "valid": true
+            },
+            {
+                "description": "a valid up and then down RJP, with array index",
+                "data": "2/0/baz/1/zip",
+                "valid": true
+            },
+            {
+                "description": "a valid RJP taking the member or index name",
+                "data": "0#",
+                "valid": true
+            },
+            {
+                "description": "an invalid RJP that is a valid JSON Pointer",
+                "data": "/foo/bar",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/time.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/time.json
new file mode 100644
index 0000000..4ec8a01
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/time.json
@@ -0,0 +1,23 @@
+[
+    {
+        "description": "validation of time strings",
+        "schema": {"format": "time"},
+        "tests": [
+            {
+                "description": "a valid time string",
+                "data": "08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "an invalid time string",
+                "data": "08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "01:01:01,1111",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri-reference.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri-reference.json
new file mode 100644
index 0000000..e4c9eef
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri-reference.json
@@ -0,0 +1,43 @@
+[
+    {
+        "description": "validation of URI References",
+        "schema": {"format": "uri-reference"},
+        "tests": [
+            {
+                "description": "a valid URI",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid relative URI Reference",
+                "data": "/abc",
+                "valid": true
+            },
+            {
+                "description": "an invalid URI Reference",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "a valid URI Reference",
+                "data": "abc",
+                "valid": true
+            },
+            {
+                "description": "a valid URI fragment",
+                "data": "#fragment",
+                "valid": true
+            },
+            {
+                "description": "an invalid URI fragment",
+                "data": "#frag\\ment",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri-template.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri-template.json
new file mode 100644
index 0000000..33ab76e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri-template.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "format: uri-template",
+        "schema": {"format": "uri-template"},
+        "tests": [
+            {
+                "description": "a valid uri-template",
+                "data": "http://example.com/dictionary/{term:1}/{term}",
+                "valid": true
+            },
+            {
+                "description": "an invalid uri-template",
+                "data": "http://example.com/dictionary/{term:1}/{term",
+                "valid": false
+            },
+            {
+                "description": "a valid uri-template without variables",
+                "data": "http://example.com/dictionary",
+                "valid": true
+            },
+            {
+                "description": "a valid relative uri-template",
+                "data": "dictionary/{term:1}/{term}",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri.json
new file mode 100644
index 0000000..25cc40c
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/uri.json
@@ -0,0 +1,103 @@
+[
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "a valid URL with anchor tag",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with anchor tag and parantheses",
+                "data": "http://foo.com/blah_(wikipedia)_blah#cite-1",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with URL-encoded stuff",
+                "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff",
+                "valid": true
+            },
+            {
+                "description": "a valid puny-coded URL ",
+                "data": "http://xn--nw2a.xn--j6w193g/",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with many special characters",
+                "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid URL based on IPv4",
+                "data": "http://223.255.255.254",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with ftp scheme",
+                "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL for a simple text file",
+                "data": "http://www.ietf.org/rfc/rfc2396.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL ",
+                "data": "ldap://[2001:db8::7]/c=GB?objectClass?one",
+                "valid": true
+            },
+            {
+                "description": "a valid mailto URI",
+                "data": "mailto:John.Doe@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid newsgroup URI",
+                "data": "news:comp.infosystems.www.servers.unix",
+                "valid": true
+            },
+            {
+                "description": "a valid tel URI",
+                "data": "tel:+1-816-555-1212",
+                "valid": true
+            },
+            {
+                "description": "a valid URN",
+                "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
+                "valid": true
+            },
+            {
+                "description": "an invalid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": false
+            },
+            {
+                "description": "an invalid relative URI Reference",
+                "data": "/abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI though valid URI reference",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces",
+                "data": "http:// shouldfail.com",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces and missing scheme",
+                "data": ":// should fail",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/optional/zeroTerminatedFloats.json b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..1bcdf96
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+    {
+        "description": "some languages do not distinguish between different types of numeric value",
+        "schema": {
+            "type": "integer"
+        },
+        "tests": [
+            {
+                "description": "a float without fractional part is an integer",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/pattern.json b/JSON-Schema-Test-Suite/tests/draft2019-09/pattern.json
new file mode 100644
index 0000000..25e7299
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/pattern.json
@@ -0,0 +1,34 @@
+[
+    {
+        "description": "pattern validation",
+        "schema": {"pattern": "^a*$"},
+        "tests": [
+            {
+                "description": "a matching pattern is valid",
+                "data": "aaa",
+                "valid": true
+            },
+            {
+                "description": "a non-matching pattern is invalid",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": true,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "pattern is not anchored",
+        "schema": {"pattern": "a+"},
+        "tests": [
+            {
+                "description": "matches a substring",
+                "data": "xxaayy",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/patternProperties.json b/JSON-Schema-Test-Suite/tests/draft2019-09/patternProperties.json
new file mode 100644
index 0000000..1d04a16
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/patternProperties.json
@@ -0,0 +1,151 @@
+[
+    {
+        "description":
+            "patternProperties validates properties matching a regex",
+        "schema": {
+            "patternProperties": {
+                "f.*o": {"type": "integer"}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "multiple valid matches is valid",
+                "data": {"foo": 1, "foooooo" : 2},
+                "valid": true
+            },
+            {
+                "description": "a single invalid match is invalid",
+                "data": {"foo": "bar", "fooooo": 2},
+                "valid": false
+            },
+            {
+                "description": "multiple invalid matches is invalid",
+                "data": {"foo": "bar", "foooooo" : "baz"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple simultaneous patternProperties are validated",
+        "schema": {
+            "patternProperties": {
+                "a*": {"type": "integer"},
+                "aaa*": {"maximum": 20}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"a": 21},
+                "valid": true
+            },
+            {
+                "description": "a simultaneous match is valid",
+                "data": {"aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "multiple matches is valid",
+                "data": {"a": 21, "aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "an invalid due to one is invalid",
+                "data": {"a": "bar"},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to the other is invalid",
+                "data": {"aaaa": 31},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to both is invalid",
+                "data": {"aaa": "foo", "aaaa": 31},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "regexes are not anchored by default and are case sensitive",
+        "schema": {
+            "patternProperties": {
+                "[0-9]{2,}": { "type": "boolean" },
+                "X_": { "type": "string" }
+            }
+        },
+        "tests": [
+            {
+                "description": "non recognized members are ignored",
+                "data": { "answer 1": "42" },
+                "valid": true
+            },
+            {
+                "description": "recognized members are accounted for",
+                "data": { "a31b": null },
+                "valid": false
+            },
+            {
+                "description": "regexes are case sensitive",
+                "data": { "a_x_3": 3 },
+                "valid": true
+            },
+            {
+                "description": "regexes are case sensitive, 2",
+                "data": { "a_X_3": 3 },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "patternProperties with boolean schemas",
+        "schema": {
+            "patternProperties": {
+                "f.*": true,
+                "b.*": false
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property matching schema true is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "object with property matching schema false is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "object with both properties is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/properties.json b/JSON-Schema-Test-Suite/tests/draft2019-09/properties.json
new file mode 100644
index 0000000..b86c181
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/properties.json
@@ -0,0 +1,167 @@
+[
+    {
+        "description": "object properties validation",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "both properties present and valid is valid",
+                "data": {"foo": 1, "bar": "baz"},
+                "valid": true
+            },
+            {
+                "description": "one property invalid is invalid",
+                "data": {"foo": 1, "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "both properties invalid is invalid",
+                "data": {"foo": [], "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "doesn't invalidate other properties",
+                "data": {"quux": []},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description":
+            "properties, patternProperties, additionalProperties interaction",
+        "schema": {
+            "properties": {
+                "foo": {"type": "array", "maxItems": 3},
+                "bar": {"type": "array"}
+            },
+            "patternProperties": {"f.o": {"minItems": 2}},
+            "additionalProperties": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "property validates property",
+                "data": {"foo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "property invalidates property",
+                "data": {"foo": [1, 2, 3, 4]},
+                "valid": false
+            },
+            {
+                "description": "patternProperty invalidates property",
+                "data": {"foo": []},
+                "valid": false
+            },
+            {
+                "description": "patternProperty validates nonproperty",
+                "data": {"fxo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "patternProperty invalidates nonproperty",
+                "data": {"fxo": []},
+                "valid": false
+            },
+            {
+                "description": "additionalProperty ignores property",
+                "data": {"bar": []},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty validates others",
+                "data": {"quux": 3},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty invalidates others",
+                "data": {"quux": "foo"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with boolean schema",
+        "schema": {
+            "properties": {
+                "foo": true,
+                "bar": false
+            }
+        },
+        "tests": [
+            {
+                "description": "no property present is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "only 'true' property present is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "only 'false' property present is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "both properties present is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with escaped characters",
+        "schema": {
+            "properties": {
+                "foo\nbar": {"type": "number"},
+                "foo\"bar": {"type": "number"},
+                "foo\\bar": {"type": "number"},
+                "foo\rbar": {"type": "number"},
+                "foo\tbar": {"type": "number"},
+                "foo\fbar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with all numbers is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1",
+                    "foo\\bar": "1",
+                    "foo\rbar": "1",
+                    "foo\tbar": "1",
+                    "foo\fbar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/propertyNames.json b/JSON-Schema-Test-Suite/tests/draft2019-09/propertyNames.json
new file mode 100644
index 0000000..8423690
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/propertyNames.json
@@ -0,0 +1,78 @@
+[
+    {
+        "description": "propertyNames validation",
+        "schema": {
+            "propertyNames": {"maxLength": 3}
+        },
+        "tests": [
+            {
+                "description": "all property names valid",
+                "data": {
+                    "f": {},
+                    "foo": {}
+                },
+                "valid": true
+            },
+            {
+                "description": "some property names invalid",
+                "data": {
+                    "foo": {},
+                    "foobar": {}
+                },
+                "valid": false
+            },
+            {
+                "description": "object without properties is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3, 4],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "propertyNames with boolean schema true",
+        "schema": {"propertyNames": true},
+        "tests": [
+            {
+                "description": "object with any properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "propertyNames with boolean schema false",
+        "schema": {"propertyNames": false},
+        "tests": [
+            {
+                "description": "object with any properties is invalid",
+                "data": {"foo": 1},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/ref.json b/JSON-Schema-Test-Suite/tests/draft2019-09/ref.json
new file mode 100644
index 0000000..285de55
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/ref.json
@@ -0,0 +1,359 @@
+[
+    {
+        "description": "root pointer ref",
+        "schema": {
+            "properties": {
+                "foo": {"$ref": "#"}
+            },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"foo": false},
+                "valid": true
+            },
+            {
+                "description": "recursive match",
+                "data": {"foo": {"foo": false}},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": false},
+                "valid": false
+            },
+            {
+                "description": "recursive mismatch",
+                "data": {"foo": {"bar": false}},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to object",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"$ref": "#/properties/foo"}
+            }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"bar": 3},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": true},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to array",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"$ref": "#/items/0"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "match array",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "mismatch array",
+                "data": [1, "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "escaped pointer ref",
+        "schema": {
+            "tilda~field": {"type": "integer"},
+            "slash/field": {"type": "integer"},
+            "percent%field": {"type": "integer"},
+            "properties": {
+                "tilda": {"$ref": "#/tilda~0field"},
+                "slash": {"$ref": "#/slash~1field"},
+                "percent": {"$ref": "#/percent%25field"}
+            }
+        },
+        "tests": [
+            {
+                "description": "slash invalid",
+                "data": {"slash": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "tilda invalid",
+                "data": {"tilda": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "percent invalid",
+                "data": {"percent": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "slash valid",
+                "data": {"slash": 123},
+                "valid": true
+            },
+            {
+                "description": "tilda valid",
+                "data": {"tilda": 123},
+                "valid": true
+            },
+            {
+                "description": "percent valid",
+                "data": {"percent": 123},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested refs",
+        "schema": {
+            "$defs": {
+                "a": {"type": "integer"},
+                "b": {"$ref": "#/$defs/a"},
+                "c": {"$ref": "#/$defs/b"}
+            },
+            "$ref": "#/$defs/c"
+        },
+        "tests": [
+            {
+                "description": "nested ref valid",
+                "data": 5,
+                "valid": true
+            },
+            {
+                "description": "nested ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref overrides any sibling keywords",
+        "schema": {
+            "$defs": {
+                "reffed": {
+                    "type": "array"
+                }
+            },
+            "properties": {
+                "foo": {
+                    "$ref": "#/$defs/reffed",
+                    "maxItems": 2
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "ref valid",
+                "data": { "foo": [] },
+                "valid": true
+            },
+            {
+                "description": "ref valid, maxItems ignored",
+                "data": { "foo": [ 1, 2, 3] },
+                "valid": true
+            },
+            {
+                "description": "ref invalid",
+                "data": { "foo": "string" },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "remote ref, containing refs itself",
+        "schema": {"$ref": "https://json-schema.org/draft/2019-09/schema"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": {"minLength": 1},
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": {"minLength": -1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "property named $ref that is not a reference",
+        "schema": {
+            "properties": {
+                "$ref": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "property named $ref valid",
+                "data": {"$ref": "a"},
+                "valid": true
+            },
+            {
+                "description": "property named $ref invalid",
+                "data": {"$ref": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "$ref to boolean schema true",
+        "schema": {
+            "$ref": "#/$defs/bool",
+            "$defs": {
+                "bool": true
+            }
+        },
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "$ref to boolean schema false",
+        "schema": {
+            "$ref": "#/$defs/bool",
+            "$defs": {
+                "bool": false
+            }
+        },
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Recursive references between schemas",
+        "schema": {
+            "$id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+                "meta": {"type": "string"},
+                "nodes": {
+                    "type": "array",
+                    "items": {"$ref": "node"}
+                }
+            },
+            "required": ["meta", "nodes"],
+            "$defs": {
+                "node": {
+                    "$id": "http://localhost:1234/node",
+                    "description": "node",
+                    "type": "object",
+                    "properties": {
+                        "value": {"type": "number"},
+                        "subtree": {"$ref": "tree"}
+                    },
+                    "required": ["value"]
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 1.1},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": "string is invalid"},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "refs with quote",
+        "schema": {
+            "properties": {
+                "foo\"bar": {"$ref": "#/$defs/foo%22bar"}
+            },
+            "$defs": {
+                "foo\"bar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with numbers is valid",
+                "data": {
+                    "foo\"bar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/refRemote.json b/JSON-Schema-Test-Suite/tests/draft2019-09/refRemote.json
new file mode 100644
index 0000000..9cadc92
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/refRemote.json
@@ -0,0 +1,167 @@
+[
+    {
+        "description": "remote ref",
+        "schema": {"$ref": "http://localhost:1234/integer.json"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "fragment within remote ref",
+        "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},
+        "tests": [
+            {
+                "description": "remote fragment valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote fragment invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref within remote ref",
+        "schema": {
+            "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"
+        },
+        "tests": [
+            {
+                "description": "ref within ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "ref within ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change",
+        "schema": {
+            "$id": "http://localhost:1234/",
+            "items": {
+                "$id": "folder/",
+                "items": {"$ref": "folderInteger.json"}
+            }
+        },
+        "tests": [
+            {
+                "description": "base URI change ref valid",
+                "data": [[1]],
+                "valid": true
+            },
+            {
+                "description": "base URI change ref invalid",
+                "data": [["a"]],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder",
+        "schema": {
+            "$id": "http://localhost:1234/scope_change_defs1.json",
+            "type" : "object",
+            "properties": {"list": {"$ref": "#/$defs/baz"}},
+            "$defs": {
+                "baz": {
+                    "$id": "folder/",
+                    "type": "array",
+                    "items": {"$ref": "folderInteger.json"}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder in subschema",
+        "schema": {
+            "$id": "http://localhost:1234/scope_change_defs2.json",
+            "type" : "object",
+            "properties": {"list": {"$ref": "#/$defs/baz/$defs/bar"}},
+            "$defs": {
+                "baz": {
+                    "$id": "folder/",
+                    "$defs": {
+                        "bar": {
+                            "type": "array",
+                            "items": {"$ref": "folderInteger.json"}
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "root ref in remote ref",
+        "schema": {
+            "$id": "http://localhost:1234/object",
+            "type": "object",
+            "properties": {
+                "name": {"$ref": "name-defs.json#/$defs/orNull"}
+            }
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": {
+                    "name": "foo"
+                },
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": {
+                    "name": null
+                },
+                "valid": true
+            },
+            {
+                "description": "object is invalid",
+                "data": {
+                    "name": {
+                        "name": null
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/required.json b/JSON-Schema-Test-Suite/tests/draft2019-09/required.json
new file mode 100644
index 0000000..abf18f3
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/required.json
@@ -0,0 +1,105 @@
+[
+    {
+        "description": "required validation",
+        "schema": {
+            "properties": {
+                "foo": {},
+                "bar": {}
+            },
+            "required": ["foo"]
+        },
+        "tests": [
+            {
+                "description": "present required property is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "non-present required property is invalid",
+                "data": {"bar": 1},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required default validation",
+        "schema": {
+            "properties": {
+                "foo": {}
+            }
+        },
+        "tests": [
+            {
+                "description": "not required by default",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with empty array",
+        "schema": {
+            "properties": {
+                "foo": {}
+            },
+            "required": []
+        },
+        "tests": [
+            {
+                "description": "property not required",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with escaped characters",
+        "schema": {
+            "required": [
+                "foo\nbar",
+                "foo\"bar",
+                "foo\\bar",
+                "foo\rbar",
+                "foo\tbar",
+                "foo\fbar"
+            ]
+        },
+        "tests": [
+            {
+                "description": "object with all properties present is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with some properties missing is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/type.json b/JSON-Schema-Test-Suite/tests/draft2019-09/type.json
new file mode 100644
index 0000000..ea33b18
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/type.json
@@ -0,0 +1,464 @@
+[
+    {
+        "description": "integer type matches integers",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "an integer is an integer",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is not an integer",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an integer",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not an integer, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not an integer",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not an integer",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an integer",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an integer",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "number type matches numbers",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "an integer is a number",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is a number",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "a string is not a number",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not a number, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not a number",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a number",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a number",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a number",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "string type matches strings",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "1 is not a string",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not a string",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is a string",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a string is still a string, even if it looks like a number",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "an empty string is still a string",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "an object is not a string",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a string",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a string",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a string",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "object type matches objects",
+        "schema": {"type": "object"},
+        "tests": [
+            {
+                "description": "an integer is not an object",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an object",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an object",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is an object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "an array is not an object",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an object",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an object",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "array type matches arrays",
+        "schema": {"type": "array"},
+        "tests": [
+            {
+                "description": "an integer is not an array",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an array",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an array",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not an array",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is an array",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "a boolean is not an array",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an array",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "boolean type matches booleans",
+        "schema": {"type": "boolean"},
+        "tests": [
+            {
+                "description": "an integer is not a boolean",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "zero is not a boolean",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a float is not a boolean",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not a boolean",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not a boolean",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not a boolean",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a boolean",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is a boolean",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "false is a boolean",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is not a boolean",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "null type matches only the null object",
+        "schema": {"type": "null"},
+        "tests": [
+            {
+                "description": "an integer is not null",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not null",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "zero is not null",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a string is not null",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not null",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not null",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not null",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is not null",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "false is not null",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple types can be specified in an array",
+        "schema": {"type": ["integer", "string"]},
+        "tests": [
+            {
+                "description": "an integer is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a float is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "an object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type as array with one item",
+        "schema": {
+            "type": ["string"]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array or object",
+        "schema": {
+            "type": ["array", "object"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array, object or null",
+        "schema": {
+            "type": ["array", "object", "null"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft2019-09/uniqueItems.json b/JSON-Schema-Test-Suite/tests/draft2019-09/uniqueItems.json
new file mode 100644
index 0000000..d312ad7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft2019-09/uniqueItems.json
@@ -0,0 +1,173 @@
+[
+    {
+        "description": "uniqueItems validation",
+        "schema": {"uniqueItems": true},
+        "tests": [
+            {
+                "description": "unique array of integers is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of integers is invalid",
+                "data": [1, 1],
+                "valid": false
+            },
+            {
+                "description": "numbers are unique if mathematically unequal",
+                "data": [1.0, 1.00, 1],
+                "valid": false
+            },
+            {
+                "description": "false is not equal to zero",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "true is not equal to one",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "unique array of objects is valid",
+                "data": [{"foo": "bar"}, {"foo": "baz"}],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of objects is invalid",
+                "data": [{"foo": "bar"}, {"foo": "bar"}],
+                "valid": false
+            },
+            {
+                "description": "unique array of nested objects is valid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : false}}}
+                ],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of nested objects is invalid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : true}}}
+                ],
+                "valid": false
+            },
+            {
+                "description": "unique array of arrays is valid",
+                "data": [["foo"], ["bar"]],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of arrays is invalid",
+                "data": [["foo"], ["foo"]],
+                "valid": false
+            },
+            {
+                "description": "1 and true are unique",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "0 and false are unique",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "unique heterogeneous types are valid",
+                "data": [{}, [1], true, null, 1],
+                "valid": true
+            },
+            {
+                "description": "non-unique heterogeneous types are invalid",
+                "data": [{}, [1], true, null, {}, 1],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "unique array extended from [false, true] is valid",
+                "data": [false, true, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "unique array extended from [true, false] is valid",
+                "data": [true, false, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "non-unique array extended from [false, true] is not valid",
+                "data": [false, true, "foo", "foo"],
+                "valid": false
+            },
+            {
+                "description": "non-unique array extended from [true, false] is not valid",
+                "data": [true, false, "foo", "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items and additionalItems=false",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true, 
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "extra items are invalid even if unique",
+                "data": [false, true, null],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/additionalItems.json b/JSON-Schema-Test-Suite/tests/draft3/additionalItems.json
new file mode 100644
index 0000000..6d4bff5
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/additionalItems.json
@@ -0,0 +1,82 @@
+[
+    {
+        "description": "additionalItems as schema",
+        "schema": {
+            "items": [],
+            "additionalItems": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "additional items match schema",
+                "data": [ 1, 2, 3, 4 ],
+                "valid": true
+            },
+            {
+                "description": "additional items do not match schema",
+                "data": [ 1, 2, 3, "foo" ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "items is schema, no additionalItems",
+        "schema": {
+            "items": {},
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "all items match schema",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "array of items with no additionalItems",
+        "schema": {
+            "items": [{}, {}, {}],
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "no additional items present",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "additional items are not permitted",
+                "data": [ 1, 2, 3, 4 ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalItems as false without items",
+        "schema": {"additionalItems": false},
+        "tests": [
+            {
+                "description":
+                    "items defaults to empty schema so everything is valid",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalItems are allowed by default",
+        "schema": {"items": []},
+        "tests": [
+            {
+                "description": "only the first items are validated",
+                "data": [1, "foo", false],
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/additionalProperties.json b/JSON-Schema-Test-Suite/tests/draft3/additionalProperties.json
new file mode 100644
index 0000000..bfb0844
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/additionalProperties.json
@@ -0,0 +1,133 @@
+[
+    {
+        "description":
+            "additionalProperties being false does not allow other properties",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "patternProperties": { "^v": {} },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobarbaz",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "patternProperties are not additional properties",
+                "data": {"foo":1, "vroom": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "non-ASCII pattern with additionalProperties",
+        "schema": {
+            "patternProperties": {"^á": {}},
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "matching the pattern is valid",
+                "data": {"ármányos": 2},
+                "valid": true
+            },
+            {
+                "description": "not matching the pattern is invalid",
+                "data": {"élmény": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties allows a schema which should validate",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : 12},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties can exist by itself",
+        "schema": {
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties are allowed by default",
+        "schema": {"properties": {"foo": {}, "bar": {}}},
+        "tests": [
+            {
+                "description": "additional properties are allowed",
+                "data": {"foo": 1, "bar": 2, "quux": true},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties should not look in applicators",
+        "schema": {
+            "extends": [
+                {"properties": {"foo": {}}}
+            ],
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "properties defined in extends are not allowed",
+                "data": {"foo": 1, "bar": true},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/default.json b/JSON-Schema-Test-Suite/tests/draft3/default.json
new file mode 100644
index 0000000..1762977
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/default.json
@@ -0,0 +1,49 @@
+[
+    {
+        "description": "invalid type for default",
+        "schema": {
+            "properties": {
+                "foo": {
+                    "type": "integer",
+                    "default": []
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"foo": 13},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid string value for default",
+        "schema": {
+            "properties": {
+                "bar": {
+                    "type": "string",
+                    "minLength": 4,
+                    "default": "bad"
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"bar": "good"},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/dependencies.json b/JSON-Schema-Test-Suite/tests/draft3/dependencies.json
new file mode 100644
index 0000000..d7e0925
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/dependencies.json
@@ -0,0 +1,118 @@
+[
+    {
+        "description": "dependencies",
+        "schema": {
+            "dependencies": {"bar": "foo"}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependant",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "with dependency",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["bar"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies",
+        "schema": {
+            "dependencies": {"quux": ["foo", "bar"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependants",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "with dependencies",
+                "data": {"foo": 1, "bar": 2, "quux": 3},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"foo": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing other dependency",
+                "data": {"bar": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing both dependencies",
+                "data": {"quux": 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies subschema",
+        "schema": {
+            "dependencies": {
+                "bar": {
+                    "properties": {
+                        "foo": {"type": "integer"},
+                        "bar": {"type": "integer"}
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type other",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            },
+            {
+                "description": "wrong type both",
+                "data": {"foo": "quux", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/disallow.json b/JSON-Schema-Test-Suite/tests/draft3/disallow.json
new file mode 100644
index 0000000..a5c9d90
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/disallow.json
@@ -0,0 +1,80 @@
+[
+    {
+        "description": "disallow",
+        "schema": {
+            "disallow": "integer"
+        },
+        "tests": [
+            {
+                "description": "allowed",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "disallowed",
+                "data": 1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple disallow",
+        "schema": {
+            "disallow": ["integer", "boolean"]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "other mismatch",
+                "data": true,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple disallow subschema",
+        "schema": {
+            "disallow":
+                ["string",
+                 {
+                    "type": "object",
+                    "properties": {
+                        "foo": {
+                            "type": "string"
+                        }
+                    }
+                 }]
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "other match",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "other mismatch",
+                "data": {"foo": "bar"},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/divisibleBy.json b/JSON-Schema-Test-Suite/tests/draft3/divisibleBy.json
new file mode 100644
index 0000000..ef7cc14
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/divisibleBy.json
@@ -0,0 +1,60 @@
+[
+    {
+        "description": "by int",
+        "schema": {"divisibleBy": 2},
+        "tests": [
+            {
+                "description": "int by int",
+                "data": 10,
+                "valid": true
+            },
+            {
+                "description": "int by int fail",
+                "data": 7,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "by number",
+        "schema": {"divisibleBy": 1.5},
+        "tests": [
+            {
+                "description": "zero is divisible by anything (except 0)",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "4.5 is divisible by 1.5",
+                "data": 4.5,
+                "valid": true
+            },
+            {
+                "description": "35 is not divisible by 1.5",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "by small number",
+        "schema": {"divisibleBy": 0.0001},
+        "tests": [
+            {
+                "description": "0.0075 is divisible by 0.0001",
+                "data": 0.0075,
+                "valid": true
+            },
+            {
+                "description": "0.00751 is not divisible by 0.0001",
+                "data": 0.00751,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/enum.json b/JSON-Schema-Test-Suite/tests/draft3/enum.json
new file mode 100644
index 0000000..fc3e070
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/enum.json
@@ -0,0 +1,71 @@
+[
+    {
+        "description": "simple enum validation",
+        "schema": {"enum": [1, 2, 3]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": 4,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "heterogeneous enum validation",
+        "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "objects are deep compared",
+                "data": {"foo": false},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enums in properties",
+        "schema": {
+            "type":"object",
+            "properties": {
+                "foo": {"enum":["foo"]},
+                "bar": {"enum":["bar"], "required":true}
+            }
+        },
+        "tests": [
+            {
+                "description": "both properties are valid",
+                "data": {"foo":"foo", "bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing optional property is valid",
+                "data": {"bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing required property is invalid",
+                "data": {"foo":"foo"},
+                "valid": false
+            },
+            {
+                "description": "missing all properties is invalid",
+                "data": {},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/extends.json b/JSON-Schema-Test-Suite/tests/draft3/extends.json
new file mode 100644
index 0000000..909bce5
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/extends.json
@@ -0,0 +1,94 @@
+[
+    {
+        "description": "extends",
+        "schema": {
+            "properties": {"bar": {"type": "integer", "required": true}},
+            "extends": {
+                "properties": {
+                    "foo": {"type": "string", "required": true}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "extends",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "mismatch extends",
+                "data": {"foo": "baz"},
+                "valid": false
+            },
+            {
+                "description": "mismatch extended",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "baz", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple extends",
+        "schema": {
+            "properties": {"bar": {"type": "integer", "required": true}},
+            "extends" : [
+                {
+                    "properties": {
+                        "foo": {"type": "string", "required": true}
+                    }
+                },
+                {
+                    "properties": {
+                        "baz": {"type": "null", "required": true}
+                    }
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": "quux", "bar": 2, "baz": null},
+                "valid": true
+            },
+            {
+                "description": "mismatch first extends",
+                "data": {"bar": 2, "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch second extends",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "mismatch both",
+                "data": {"bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "extends simple types",
+        "schema": {
+            "minimum": 20,
+            "extends": {"maximum": 30}
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": 25,
+                "valid": true
+            },
+            {
+                "description": "mismatch extends",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/format.json b/JSON-Schema-Test-Suite/tests/draft3/format.json
new file mode 100644
index 0000000..8279336
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/format.json
@@ -0,0 +1,362 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ip-address"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of hostnames",
+        "schema": {"format": "host-name"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of regular expressions",
+        "schema": {"format": "regex"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date strings",
+        "schema": {"format": "date"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of time strings",
+        "schema": {"format": "time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of CSS colors",
+        "schema": {"format": "color"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/items.json b/JSON-Schema-Test-Suite/tests/draft3/items.json
new file mode 100644
index 0000000..f5e18a1
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/items.json
@@ -0,0 +1,46 @@
+[
+    {
+        "description": "a schema given for items",
+        "schema": {
+            "items": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "wrong type of items",
+                "data": [1, "x"],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "an array of schemas for items",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"type": "string"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "correct types",
+                "data": [ 1, "foo" ],
+                "valid": true
+            },
+            {
+                "description": "wrong types",
+                "data": [ "foo", 1 ],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/maxItems.json b/JSON-Schema-Test-Suite/tests/draft3/maxItems.json
new file mode 100644
index 0000000..3b53a6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/maxItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maxItems validation",
+        "schema": {"maxItems": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "foobar",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/maxLength.json b/JSON-Schema-Test-Suite/tests/draft3/maxLength.json
new file mode 100644
index 0000000..4de42bc
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/maxLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "maxLength validation",
+        "schema": {"maxLength": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": "f",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 10,
+                "valid": true
+            },
+            {
+                "description": "two supplementary Unicode code points is long enough",
+                "data": "\uD83D\uDCA9\uD83D\uDCA9",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/maximum.json b/JSON-Schema-Test-Suite/tests/draft3/maximum.json
new file mode 100644
index 0000000..86c7b89
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/maximum.json
@@ -0,0 +1,42 @@
+[
+    {
+        "description": "maximum validation",
+        "schema": {"maximum": 3.0},
+        "tests": [
+            {
+                "description": "below the maximum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "above the maximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "exclusiveMaximum validation",
+        "schema": {
+            "maximum": 3.0,
+            "exclusiveMaximum": true
+        },
+        "tests": [
+            {
+                "description": "below the maximum is still valid",
+                "data": 2.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 3.0,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/minItems.json b/JSON-Schema-Test-Suite/tests/draft3/minItems.json
new file mode 100644
index 0000000..ed51188
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/minItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "minItems validation",
+        "schema": {"minItems": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/minLength.json b/JSON-Schema-Test-Suite/tests/draft3/minLength.json
new file mode 100644
index 0000000..3f09158
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/minLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "minLength validation",
+        "schema": {"minLength": 2},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": "f",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "one supplementary Unicode code point is not long enough",
+                "data": "\uD83D\uDCA9",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/minimum.json b/JSON-Schema-Test-Suite/tests/draft3/minimum.json
new file mode 100644
index 0000000..5ac9fee
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/minimum.json
@@ -0,0 +1,73 @@
+[
+    {
+        "description": "minimum validation",
+        "schema": {"minimum": 1.1},
+        "tests": [
+            {
+                "description": "above the minimum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "exclusiveMinimum validation",
+        "schema": {
+            "minimum": 1.1,
+            "exclusiveMinimum": true
+        },
+        "tests": [
+            {
+                "description": "above the minimum is still valid",
+                "data": 1.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 1.1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "minimum validation with signed integer",
+        "schema": {"minimum": -2},
+        "tests": [
+            {
+                "description": "negative above the minimum is valid",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "positive above the minimum is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": -2,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": -3,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/optional/bignum.json b/JSON-Schema-Test-Suite/tests/draft3/optional/bignum.json
new file mode 100644
index 0000000..ccc7c17
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/optional/bignum.json
@@ -0,0 +1,107 @@
+[
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a bignum is an integer",
+                "data": 12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a bignum is a number",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a negative bignum is an integer",
+                "data": -12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a negative bignum is a number",
+                "data": -98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "string",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "a bignum is not a string",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"maximum": 18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision",
+        "schema": {
+            "maximum": 972783798187987123879878123.18878137,
+            "exclusiveMaximum": true
+        },
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"minimum": -18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision on negative numbers",
+        "schema": {
+            "minimum": -972783798187987123879878123.18878137,
+            "exclusiveMinimum": true
+        },
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/optional/ecmascript-regex.json b/JSON-Schema-Test-Suite/tests/draft3/optional/ecmascript-regex.json
new file mode 100644
index 0000000..03fe977
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/optional/ecmascript-regex.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "ECMA 262 regex dialect recognition",
+        "schema": { "format": "regex" },
+        "tests": [
+            {
+                "description": "[^] is a valid regex",
+                "data": "[^]",
+                "valid": true
+            },
+            {
+                "description": "ECMA 262 has no support for lookbehind",
+                "data": "(?<=foo)bar",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/optional/format.json b/JSON-Schema-Test-Suite/tests/draft3/optional/format.json
new file mode 100644
index 0000000..9864589
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/optional/format.json
@@ -0,0 +1,227 @@
+[
+    {
+        "description": "validation of regular expressions",
+        "schema": {"format": "regex"},
+        "tests": [
+            {
+                "description": "a valid regular expression",
+                "data": "([abc])+\\s+$",
+                "valid": true
+            },
+            {
+                "description": "a regular expression with unclosed parens is invalid",
+                "data": "^(abc]",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "a valid date-time string",
+                "data": "1963-06-19T08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963 08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "case-insensitive T and Z",
+                "data": "1963-06-19t08:30:06.283185z",
+                "valid": true
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350T01:01:01",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of date strings",
+        "schema": {"format": "date"},
+        "tests": [
+            {
+                "description": "a valid date string",
+                "data": "1963-06-19",
+                "valid": true
+            },
+            {
+                "description": "an invalid date string",
+                "data": "06/19/1963",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of time strings",
+        "schema": {"format": "time"},
+        "tests": [
+            {
+                "description": "a valid time string",
+                "data": "08:30:06",
+                "valid": true
+            },
+            {
+                "description": "an invalid time string",
+                "data": "8:30 AM",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "a valid URI",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "an invalid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI though valid URI reference",
+                "data": "abc",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "a valid e-mail address",
+                "data": "joe.bloggs@example.com",
+                "valid": true
+            },
+            {
+                "description": "an invalid e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ip-address"},
+        "tests": [
+            {
+                "description": "a valid IP address",
+                "data": "192.168.0.1",
+                "valid": true
+            },
+            {
+                "description": "an IP address with too many components",
+                "data": "127.0.0.0.1",
+                "valid": false
+            },
+            {
+                "description": "an IP address with out-of-range values",
+                "data": "256.256.256.256",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "a valid IPv6 address",
+                "data": "::1",
+                "valid": true
+            },
+            {
+                "description": "an IPv6 address with out-of-range values",
+                "data": "12345::",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address with too many components",
+                "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address containing illegal characters",
+                "data": "::laptop",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of host names",
+        "schema": {"format": "host-name"},
+        "tests": [
+            {
+                "description": "a valid host name",
+                "data": "www.example.com",
+                "valid": true
+            },
+            {
+                "description": "a host name starting with an illegal character",
+                "data": "-a-host-name-that-starts-with--",
+                "valid": false
+            },
+            {
+                "description": "a host name containing illegal characters",
+                "data": "not_a_valid_host_name",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of CSS colors",
+        "schema": {"format": "color"},
+        "tests": [
+            {
+                "description": "a valid CSS color name",
+                "data": "fuchsia",
+                "valid": true
+            },
+            {
+                "description": "a valid six-digit CSS color code",
+                "data": "#CC8899",
+                "valid": true
+            },
+            {
+                "description": "a valid three-digit CSS color code",
+                "data": "#C89",
+                "valid": true
+            },
+            {
+                "description": "an invalid CSS color code",
+                "data": "#00332520",
+                "valid": false
+            },
+            {
+                "description": "an invalid CSS color name",
+                "data": "puce",
+                "valid": false
+            },
+            {
+                "description": "a CSS color name containing invalid characters",
+                "data": "light_grayish_red-violet",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/optional/zeroTerminatedFloats.json b/JSON-Schema-Test-Suite/tests/draft3/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..9b50ea2
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+    {
+        "description": "some languages do not distinguish between different types of numeric value",
+        "schema": {
+            "type": "integer"
+        },
+        "tests": [
+            {
+                "description": "a float is not an integer even without fractional part",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/pattern.json b/JSON-Schema-Test-Suite/tests/draft3/pattern.json
new file mode 100644
index 0000000..25e7299
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/pattern.json
@@ -0,0 +1,34 @@
+[
+    {
+        "description": "pattern validation",
+        "schema": {"pattern": "^a*$"},
+        "tests": [
+            {
+                "description": "a matching pattern is valid",
+                "data": "aaa",
+                "valid": true
+            },
+            {
+                "description": "a non-matching pattern is invalid",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": true,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "pattern is not anchored",
+        "schema": {"pattern": "a+"},
+        "tests": [
+            {
+                "description": "matches a substring",
+                "data": "xxaayy",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/patternProperties.json b/JSON-Schema-Test-Suite/tests/draft3/patternProperties.json
new file mode 100644
index 0000000..2ca9aae
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/patternProperties.json
@@ -0,0 +1,115 @@
+[
+    {
+        "description":
+            "patternProperties validates properties matching a regex",
+        "schema": {
+            "patternProperties": {
+                "f.*o": {"type": "integer"}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "multiple valid matches is valid",
+                "data": {"foo": 1, "foooooo" : 2},
+                "valid": true
+            },
+            {
+                "description": "a single invalid match is invalid",
+                "data": {"foo": "bar", "fooooo": 2},
+                "valid": false
+            },
+            {
+                "description": "multiple invalid matches is invalid",
+                "data": {"foo": "bar", "foooooo" : "baz"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple simultaneous patternProperties are validated",
+        "schema": {
+            "patternProperties": {
+                "a*": {"type": "integer"},
+                "aaa*": {"maximum": 20}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"a": 21},
+                "valid": true
+            },
+            {
+                "description": "a simultaneous match is valid",
+                "data": {"aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "multiple matches is valid",
+                "data": {"a": 21, "aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "an invalid due to one is invalid",
+                "data": {"a": "bar"},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to the other is invalid",
+                "data": {"aaaa": 31},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to both is invalid",
+                "data": {"aaa": "foo", "aaaa": 31},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "regexes are not anchored by default and are case sensitive",
+        "schema": {
+            "patternProperties": {
+                "[0-9]{2,}": { "type": "boolean" },
+                "X_": { "type": "string" }
+            }
+        },
+        "tests": [
+            {
+                "description": "non recognized members are ignored",
+                "data": { "answer 1": "42" },
+                "valid": true
+            },
+            {
+                "description": "recognized members are accounted for",
+                "data": { "a31b": null },
+                "valid": false
+            },
+            {
+                "description": "regexes are case sensitive",
+                "data": { "a_x_3": 3 },
+                "valid": true
+            },
+            {
+                "description": "regexes are case sensitive, 2",
+                "data": { "a_X_3": 3 },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/properties.json b/JSON-Schema-Test-Suite/tests/draft3/properties.json
new file mode 100644
index 0000000..a830c67
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/properties.json
@@ -0,0 +1,97 @@
+[
+    {
+        "description": "object properties validation",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "both properties present and valid is valid",
+                "data": {"foo": 1, "bar": "baz"},
+                "valid": true
+            },
+            {
+                "description": "one property invalid is invalid",
+                "data": {"foo": 1, "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "both properties invalid is invalid",
+                "data": {"foo": [], "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "doesn't invalidate other properties",
+                "data": {"quux": []},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description":
+            "properties, patternProperties, additionalProperties interaction",
+        "schema": {
+            "properties": {
+                "foo": {"type": "array", "maxItems": 3},
+                "bar": {"type": "array"}
+            },
+            "patternProperties": {"f.o": {"minItems": 2}},
+            "additionalProperties": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "property validates property",
+                "data": {"foo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "property invalidates property",
+                "data": {"foo": [1, 2, 3, 4]},
+                "valid": false
+            },
+            {
+                "description": "patternProperty invalidates property",
+                "data": {"foo": []},
+                "valid": false
+            },
+            {
+                "description": "patternProperty validates nonproperty",
+                "data": {"fxo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "patternProperty invalidates nonproperty",
+                "data": {"fxo": []},
+                "valid": false
+            },
+            {
+                "description": "additionalProperty ignores property",
+                "data": {"bar": []},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty validates others",
+                "data": {"quux": 3},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty invalidates others",
+                "data": {"quux": "foo"},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/ref.json b/JSON-Schema-Test-Suite/tests/draft3/ref.json
new file mode 100644
index 0000000..31414ad
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/ref.json
@@ -0,0 +1,192 @@
+[
+    {
+        "description": "root pointer ref",
+        "schema": {
+            "properties": {
+                "foo": {"$ref": "#"}
+            },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"foo": false},
+                "valid": true
+            },
+            {
+                "description": "recursive match",
+                "data": {"foo": {"foo": false}},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": false},
+                "valid": false
+            },
+            {
+                "description": "recursive mismatch",
+                "data": {"foo": {"bar": false}},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to object",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"$ref": "#/properties/foo"}
+            }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"bar": 3},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": true},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to array",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"$ref": "#/items/0"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "match array",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "mismatch array",
+                "data": [1, "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "escaped pointer ref",
+        "schema": {
+            "tilda~field": {"type": "integer"},
+            "slash/field": {"type": "integer"},
+            "percent%field": {"type": "integer"},
+            "properties": {
+                "tilda": {"$ref": "#/tilda~0field"},
+                "slash": {"$ref": "#/slash~1field"},
+                "percent": {"$ref": "#/percent%25field"}
+            }
+        },
+        "tests": [
+            {
+                "description": "slash invalid",
+                "data": {"slash": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "tilda invalid",
+                "data": {"tilda": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "percent invalid",
+                "data": {"percent": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "slash valid",
+                "data": {"slash": 123},
+                "valid": true
+            },
+            {
+                "description": "tilda valid",
+                "data": {"tilda": 123},
+                "valid": true
+            },
+            {
+                "description": "percent valid",
+                "data": {"percent": 123},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested refs",
+        "schema": {
+            "definitions": {
+                "a": {"type": "integer"},
+                "b": {"$ref": "#/definitions/a"},
+                "c": {"$ref": "#/definitions/b"}
+            },
+            "$ref": "#/definitions/c"
+        },
+        "tests": [
+            {
+                "description": "nested ref valid",
+                "data": 5,
+                "valid": true
+            },
+            {
+                "description": "nested ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref overrides any sibling keywords",
+        "schema": {
+            "definitions": {
+                "reffed": {
+                    "type": "array"
+                }
+            },
+            "properties": {
+                "foo": {
+                    "$ref": "#/definitions/reffed",
+                    "maxItems": 2
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": { "foo": [] },
+                "valid": true
+            },
+            {
+                "description": "remote ref valid, maxItems ignored",
+                "data": { "foo": [ 1, 2, 3] },
+                "valid": true
+            },
+            {
+                "description": "ref invalid",
+                "data": { "foo": "string" },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "remote ref, containing refs itself",
+        "schema": {"$ref": "http://json-schema.org/draft-03/schema#"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": {"items": {"type": "integer"}},
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": {"items": {"type": 1}},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/refRemote.json b/JSON-Schema-Test-Suite/tests/draft3/refRemote.json
new file mode 100644
index 0000000..4ca8047
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/refRemote.json
@@ -0,0 +1,74 @@
+[
+    {
+        "description": "remote ref",
+        "schema": {"$ref": "http://localhost:1234/integer.json"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "fragment within remote ref",
+        "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},
+        "tests": [
+            {
+                "description": "remote fragment valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote fragment invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref within remote ref",
+        "schema": {
+            "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"
+        },
+        "tests": [
+            {
+                "description": "ref within ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "ref within ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "change resolution scope",
+        "schema": {
+            "id": "http://localhost:1234/",
+            "items": {
+                "id": "folder/",
+                "items": {"$ref": "folderInteger.json"}
+            }
+        },
+        "tests": [
+            {
+                "description": "changed scope ref valid",
+                "data": [[1]],
+                "valid": true
+            },
+            {
+                "description": "changed scope ref invalid",
+                "data": [["a"]],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/required.json b/JSON-Schema-Test-Suite/tests/draft3/required.json
new file mode 100644
index 0000000..aaaf024
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/required.json
@@ -0,0 +1,53 @@
+[
+    {
+        "description": "required validation",
+        "schema": {
+            "properties": {
+                "foo": {"required" : true},
+                "bar": {}
+            }
+        },
+        "tests": [
+            {
+                "description": "present required property is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "non-present required property is invalid",
+                "data": {"bar": 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "required default validation",
+        "schema": {
+            "properties": {
+                "foo": {}
+            }
+        },
+        "tests": [
+            {
+                "description": "not required by default",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required explicitly false validation",
+        "schema": {
+            "properties": {
+                "foo": {"required": false}
+            }
+        },
+        "tests": [
+            {
+                "description": "not required if required is false",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/type.json b/JSON-Schema-Test-Suite/tests/draft3/type.json
new file mode 100644
index 0000000..49c9b40
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/type.json
@@ -0,0 +1,489 @@
+[
+    {
+        "description": "integer type matches integers",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "an integer is an integer",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is not an integer",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an integer",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not an integer, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not an integer",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not an integer",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an integer",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an integer",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "number type matches numbers",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "an integer is a number",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is a number",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "a string is not a number",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not a number, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not a number",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a number",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a number",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a number",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "string type matches strings",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "1 is not a string",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not a string",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is a string",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a string is still a string, even if it looks like a number",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "an object is not a string",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a string",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a string",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a string",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "object type matches objects",
+        "schema": {"type": "object"},
+        "tests": [
+            {
+                "description": "an integer is not an object",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an object",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an object",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is an object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "an array is not an object",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an object",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an object",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "array type matches arrays",
+        "schema": {"type": "array"},
+        "tests": [
+            {
+                "description": "an integer is not an array",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an array",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an array",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not an array",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is an array",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "a boolean is not an array",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an array",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "boolean type matches booleans",
+        "schema": {"type": "boolean"},
+        "tests": [
+            {
+                "description": "an integer is not a boolean",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not a boolean",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not a boolean",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not a boolean",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a boolean",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is a boolean",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "null is not a boolean",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "null type matches only the null object",
+        "schema": {"type": "null"},
+        "tests": [
+            {
+                "description": "an integer is not null",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not null",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not null",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not null",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not null",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not null",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "any type matches any type",
+        "schema": {"type": "any"},
+        "tests": [
+            {
+                "description": "any type includes integers",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "any type includes float",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "any type includes string",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "any type includes object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "any type includes array",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "any type includes boolean",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "any type includes null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple types can be specified in an array",
+        "schema": {"type": ["integer", "string"]},
+        "tests": [
+            {
+                "description": "an integer is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a float is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "an object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "types can include schemas",
+        "schema": {
+            "type": [
+                "array",
+                {"type": "object"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "an integer is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a float is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "an object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "an array is valid",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "a boolean is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": 
+            "when types includes a schema it should fully validate the schema",
+        "schema": {
+            "type": [
+                "integer",
+                {
+                    "properties": {
+                        "foo": {"type": "null"}
+                    }
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "an integer is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "an object is valid only if it is fully valid",
+                "data": {"foo": null},
+                "valid": true
+            },
+            {
+                "description": "an object is invalid otherwise",
+                "data": {"foo": "bar"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "types from separate schemas are merged",
+        "schema": {
+            "type": [
+                {"type": ["string"]},
+                {"type": ["array", "null"]}
+            ]
+        },
+        "tests": [
+            {
+                "description": "an integer is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "an array is valid",
+                "data": [1, 2, 3],
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft3/uniqueItems.json b/JSON-Schema-Test-Suite/tests/draft3/uniqueItems.json
new file mode 100644
index 0000000..59e3542
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft3/uniqueItems.json
@@ -0,0 +1,163 @@
+[
+    {
+        "description": "uniqueItems validation",
+        "schema": {"uniqueItems": true},
+        "tests": [
+            {
+                "description": "unique array of integers is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of integers is invalid",
+                "data": [1, 1],
+                "valid": false
+            },
+            {
+                "description": "numbers are unique if mathematically unequal",
+                "data": [1.0, 1.00, 1],
+                "valid": false
+            },
+            {
+                "description": "unique array of objects is valid",
+                "data": [{"foo": "bar"}, {"foo": "baz"}],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of objects is invalid",
+                "data": [{"foo": "bar"}, {"foo": "bar"}],
+                "valid": false
+            },
+            {
+                "description": "unique array of nested objects is valid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : false}}}
+                ],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of nested objects is invalid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : true}}}
+                ],
+                "valid": false
+            },
+            {
+                "description": "unique array of arrays is valid",
+                "data": [["foo"], ["bar"]],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of arrays is invalid",
+                "data": [["foo"], ["foo"]],
+                "valid": false
+            },
+            {
+                "description": "1 and true are unique",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "0 and false are unique",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "unique heterogeneous types are valid",
+                "data": [{}, [1], true, null, 1],
+                "valid": true
+            },
+            {
+                "description": "non-unique heterogeneous types are invalid",
+                "data": [{}, [1], true, null, {}, 1],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "unique array extended from [false, true] is valid",
+                "data": [false, true, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "unique array extended from [true, false] is valid",
+                "data": [true, false, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "non-unique array extended from [false, true] is not valid",
+                "data": [false, true, "foo", "foo"],
+                "valid": false
+            },
+            {
+                "description": "non-unique array extended from [true, false] is not valid",
+                "data": [true, false, "foo", "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items and additionalItems=false",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true, 
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "extra items are invalid even if unique",
+                "data": [false, true, null],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/additionalItems.json b/JSON-Schema-Test-Suite/tests/draft4/additionalItems.json
new file mode 100644
index 0000000..abecc57
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/additionalItems.json
@@ -0,0 +1,87 @@
+[
+    {
+        "description": "additionalItems as schema",
+        "schema": {
+            "items": [{}],
+            "additionalItems": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "additional items match schema",
+                "data": [ null, 2, 3, 4 ],
+                "valid": true
+            },
+            {
+                "description": "additional items do not match schema",
+                "data": [ null, 2, 3, "foo" ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "items is schema, no additionalItems",
+        "schema": {
+            "items": {},
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "all items match schema",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "array of items with no additionalItems",
+        "schema": {
+            "items": [{}, {}, {}],
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "fewer number of items present",
+                "data": [ 1, 2 ],
+                "valid": true
+            },
+            {
+                "description": "equal number of items present",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "additional items are not permitted",
+                "data": [ 1, 2, 3, 4 ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalItems as false without items",
+        "schema": {"additionalItems": false},
+        "tests": [
+            {
+                "description":
+                    "items defaults to empty schema so everything is valid",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalItems are allowed by default",
+        "schema": {"items": [{"type": "integer"}]},
+        "tests": [
+            {
+                "description": "only the first item is validated",
+                "data": [1, "foo", false],
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json b/JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json
new file mode 100644
index 0000000..ffeac6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json
@@ -0,0 +1,133 @@
+[
+    {
+        "description":
+            "additionalProperties being false does not allow other properties",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "patternProperties": { "^v": {} },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobarbaz",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "patternProperties are not additional properties",
+                "data": {"foo":1, "vroom": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "non-ASCII pattern with additionalProperties",
+        "schema": {
+            "patternProperties": {"^á": {}},
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "matching the pattern is valid",
+                "data": {"ármányos": 2},
+                "valid": true
+            },
+            {
+                "description": "not matching the pattern is invalid",
+                "data": {"élmény": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties allows a schema which should validate",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : 12},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties can exist by itself",
+        "schema": {
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties are allowed by default",
+        "schema": {"properties": {"foo": {}, "bar": {}}},
+        "tests": [
+            {
+                "description": "additional properties are allowed",
+                "data": {"foo": 1, "bar": 2, "quux": true},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties should not look in applicators",
+        "schema": {
+            "allOf": [
+                {"properties": {"foo": {}}}
+            ],
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "properties defined in allOf are not allowed",
+                "data": {"foo": 1, "bar": true},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/allOf.json b/JSON-Schema-Test-Suite/tests/draft4/allOf.json
new file mode 100644
index 0000000..ce9fdd4
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/allOf.json
@@ -0,0 +1,185 @@
+[
+    {
+        "description": "allOf",
+        "schema": {
+            "allOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "allOf",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "mismatch second",
+                "data": {"foo": "baz"},
+                "valid": false
+            },
+            {
+                "description": "mismatch first",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "baz", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with base schema",
+        "schema": {
+            "properties": {"bar": {"type": "integer"}},
+            "required": ["bar"],
+            "allOf" : [
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                },
+                {
+                    "properties": {
+                        "baz": {"type": "null"}
+                    },
+                    "required": ["baz"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": "quux", "bar": 2, "baz": null},
+                "valid": true
+            },
+            {
+                "description": "mismatch base schema",
+                "data": {"foo": "quux", "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch first allOf",
+                "data": {"bar": 2, "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch second allOf",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "mismatch both",
+                "data": {"bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf simple types",
+        "schema": {
+            "allOf": [
+                {"maximum": 30},
+                {"minimum": 20}
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": 25,
+                "valid": true
+            },
+            {
+                "description": "mismatch one",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with one empty schema",
+        "schema": {
+            "allOf": [
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with two empty schemas",
+        "schema": {
+            "allOf": [
+                {},
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with the first empty schema",
+        "schema": {
+            "allOf": [
+                {},
+                { "type": "number" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with the last empty schema",
+        "schema": {
+            "allOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/anyOf.json b/JSON-Schema-Test-Suite/tests/draft4/anyOf.json
new file mode 100644
index 0000000..09cc3c2
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/anyOf.json
@@ -0,0 +1,156 @@
+[
+    {
+        "description": "anyOf",
+        "schema": {
+            "anyOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid",
+                "data": 3,
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with base schema",
+        "schema": {
+            "type": "string",
+            "anyOf" : [
+                {
+                    "maxLength": 2
+                },
+                {
+                    "minLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one anyOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both anyOf invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf complex types",
+        "schema": {
+            "anyOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with one empty schema",
+        "schema": {
+            "anyOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is valid",
+                "data": 123,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested anyOf, to check validation semantics",
+        "schema": {
+            "anyOf": [
+                {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        }
+                    ]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "anything non-null is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/default.json b/JSON-Schema-Test-Suite/tests/draft4/default.json
new file mode 100644
index 0000000..1762977
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/default.json
@@ -0,0 +1,49 @@
+[
+    {
+        "description": "invalid type for default",
+        "schema": {
+            "properties": {
+                "foo": {
+                    "type": "integer",
+                    "default": []
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"foo": 13},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid string value for default",
+        "schema": {
+            "properties": {
+                "bar": {
+                    "type": "string",
+                    "minLength": 4,
+                    "default": "bad"
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"bar": "good"},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/definitions.json b/JSON-Schema-Test-Suite/tests/draft4/definitions.json
new file mode 100644
index 0000000..cf935a3
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/definitions.json
@@ -0,0 +1,32 @@
+[
+    {
+        "description": "valid definition",
+        "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
+        "tests": [
+            {
+                "description": "valid definition schema",
+                "data": {
+                    "definitions": {
+                        "foo": {"type": "integer"}
+                    }
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid definition",
+        "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
+        "tests": [
+            {
+                "description": "invalid definition schema",
+                "data": {
+                    "definitions": {
+                        "foo": {"type": 1}
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/dependencies.json b/JSON-Schema-Test-Suite/tests/draft4/dependencies.json
new file mode 100644
index 0000000..51eeddf
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/dependencies.json
@@ -0,0 +1,194 @@
+[
+    {
+        "description": "dependencies",
+        "schema": {
+            "dependencies": {"bar": ["foo"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependant",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "with dependency",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["bar"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies",
+        "schema": {
+            "dependencies": {"quux": ["foo", "bar"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependants",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "with dependencies",
+                "data": {"foo": 1, "bar": 2, "quux": 3},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"foo": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing other dependency",
+                "data": {"bar": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing both dependencies",
+                "data": {"quux": 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies subschema",
+        "schema": {
+            "dependencies": {
+                "bar": {
+                    "properties": {
+                        "foo": {"type": "integer"},
+                        "bar": {"type": "integer"}
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "no dependency",
+                "data": {"foo": "quux"},
+                "valid": true
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type other",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            },
+            {
+                "description": "wrong type both",
+                "data": {"foo": "quux", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "dependencies with escaped characters",
+        "schema": {
+            "dependencies": {
+                "foo\nbar": ["foo\rbar"],
+                "foo\tbar": {
+                    "minProperties": 4
+                },
+                "foo'bar": {"required": ["foo\"bar"]},
+                "foo\"bar": ["foo'bar"]
+            }
+        },
+        "tests": [
+            {
+                "description": "valid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\rbar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2,
+                    "b": 3,
+                    "c": 4
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 3",
+                "data": {
+                    "foo'bar": 1,
+                    "foo\"bar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 3",
+                "data": {
+                    "foo'bar": 1
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 4",
+                "data": {
+                    "foo\"bar": 2
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/enum.json b/JSON-Schema-Test-Suite/tests/draft4/enum.json
new file mode 100644
index 0000000..32d7902
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/enum.json
@@ -0,0 +1,179 @@
+[
+    {
+        "description": "simple enum validation",
+        "schema": {"enum": [1, 2, 3]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": 4,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "heterogeneous enum validation",
+        "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "objects are deep compared",
+                "data": {"foo": false},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enums in properties",
+        "schema": {
+            "type":"object",
+            "properties": {
+                "foo": {"enum":["foo"]},
+                "bar": {"enum":["bar"]}
+            },
+            "required": ["bar"]
+        },
+        "tests": [
+            {
+                "description": "both properties are valid",
+                "data": {"foo":"foo", "bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing optional property is valid",
+                "data": {"bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing required property is invalid",
+                "data": {"foo":"foo"},
+                "valid": false
+            },
+            {
+                "description": "missing all properties is invalid",
+                "data": {},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with escaped characters",
+        "schema": {
+            "enum": ["foo\nbar", "foo\rbar"]
+        },
+        "tests": [
+            {
+                "description": "member 1 is valid",
+                "data": "foo\nbar",
+                "valid": true
+            },
+            {
+                "description": "member 2 is valid",
+                "data": "foo\rbar",
+                "valid": true
+            },
+            {
+                "description": "another string is invalid",
+                "data": "abc",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with false does not match 0",
+        "schema": {"enum": [false]},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with true does not match 1",
+        "schema": {"enum": [true]},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with 0 does not match false",
+        "schema": {"enum": [0]},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "enum with 1 does not match true",
+        "schema": {"enum": [1]},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/format.json b/JSON-Schema-Test-Suite/tests/draft4/format.json
new file mode 100644
index 0000000..61e4b62
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/format.json
@@ -0,0 +1,218 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of hostnames",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/items.json b/JSON-Schema-Test-Suite/tests/draft4/items.json
new file mode 100644
index 0000000..7bf9f02
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/items.json
@@ -0,0 +1,195 @@
+[
+    {
+        "description": "a schema given for items",
+        "schema": {
+            "items": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "wrong type of items",
+                "data": [1, "x"],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "length": 1
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "an array of schemas for items",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"type": "string"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "correct types",
+                "data": [ 1, "foo" ],
+                "valid": true
+            },
+            {
+                "description": "wrong types",
+                "data": [ "foo", 1 ],
+                "valid": false
+            },
+            {
+                "description": "incomplete array of items",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with additional items",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array",
+                "data": [ ],
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "1": "valid",
+                    "length": 2
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items and subitems",
+        "schema": {
+            "definitions": {
+                "item": {
+                    "type": "array",
+                    "additionalItems": false,
+                    "items": [
+                        { "$ref": "#/definitions/sub-item" },
+                        { "$ref": "#/definitions/sub-item" }
+                    ]
+                },
+                "sub-item": {
+                    "type": "object",
+                    "required": ["foo"]
+                }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+                { "$ref": "#/definitions/item" },
+                { "$ref": "#/definitions/item" },
+                { "$ref": "#/definitions/item" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": true
+            },
+            {
+                "description": "too many items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "too many sub-items",
+                "data": [
+                    [ {"foo": null}, {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong item",
+                "data": [
+                    {"foo": null},
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong sub-item",
+                "data": [
+                    [ {}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "fewer items is valid",
+                "data": [
+                    [ {"foo": null} ],
+                    [ {"foo": null} ]
+                ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested items",
+        "schema": {
+            "type": "array",
+            "items": {
+                "type": "array",
+                "items": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {
+                            "type": "number"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid nested array",
+                "data": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": true
+            },
+            {
+                "description": "nested array with invalid type",
+                "data": [[[["1"]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": false
+            },
+            {
+                "description": "not deep enough",
+                "data": [[[1], [2],[3]], [[4], [5], [6]]],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/maxItems.json b/JSON-Schema-Test-Suite/tests/draft4/maxItems.json
new file mode 100644
index 0000000..3b53a6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/maxItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maxItems validation",
+        "schema": {"maxItems": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "foobar",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/maxLength.json b/JSON-Schema-Test-Suite/tests/draft4/maxLength.json
new file mode 100644
index 0000000..811d35b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/maxLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "maxLength validation",
+        "schema": {"maxLength": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": "f",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            },
+            {
+                "description": "two supplementary Unicode code points is long enough",
+                "data": "\uD83D\uDCA9\uD83D\uDCA9",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/maxProperties.json b/JSON-Schema-Test-Suite/tests/draft4/maxProperties.json
new file mode 100644
index 0000000..513731e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/maxProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "maxProperties validation",
+        "schema": {"maxProperties": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": {"foo": 1, "bar": 2, "baz": 3},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/maximum.json b/JSON-Schema-Test-Suite/tests/draft4/maximum.json
new file mode 100644
index 0000000..02581f6
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/maximum.json
@@ -0,0 +1,73 @@
+[
+    {
+        "description": "maximum validation",
+        "schema": {"maximum": 3.0},
+        "tests": [
+            {
+                "description": "below the maximum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 3.0,
+                "valid": true
+            },
+            {
+                "description": "above the maximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "maximum validation (explicit false exclusivity)",
+        "schema": {"maximum": 3.0, "exclusiveMaximum": false},
+        "tests": [
+            {
+                "description": "below the maximum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 3.0,
+                "valid": true
+            },
+            {
+                "description": "above the maximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "exclusiveMaximum validation",
+        "schema": {
+            "maximum": 3.0,
+            "exclusiveMaximum": true
+        },
+        "tests": [
+            {
+                "description": "below the maximum is still valid",
+                "data": 2.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 3.0,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/minItems.json b/JSON-Schema-Test-Suite/tests/draft4/minItems.json
new file mode 100644
index 0000000..ed51188
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/minItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "minItems validation",
+        "schema": {"minItems": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/minLength.json b/JSON-Schema-Test-Suite/tests/draft4/minLength.json
new file mode 100644
index 0000000..3f09158
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/minLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "minLength validation",
+        "schema": {"minLength": 2},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": "f",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "one supplementary Unicode code point is not long enough",
+                "data": "\uD83D\uDCA9",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/minProperties.json b/JSON-Schema-Test-Suite/tests/draft4/minProperties.json
new file mode 100644
index 0000000..49a0726
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/minProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "minProperties validation",
+        "schema": {"minProperties": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/minimum.json b/JSON-Schema-Test-Suite/tests/draft4/minimum.json
new file mode 100644
index 0000000..6becf2a
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/minimum.json
@@ -0,0 +1,104 @@
+[
+    {
+        "description": "minimum validation",
+        "schema": {"minimum": 1.1},
+        "tests": [
+            {
+                "description": "above the minimum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "minimum validation (explicit false exclusivity)",
+        "schema": {"minimum": 1.1, "exclusiveMinimum": false},
+        "tests": [
+            {
+                "description": "above the minimum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "exclusiveMinimum validation",
+        "schema": {
+            "minimum": 1.1,
+            "exclusiveMinimum": true
+        },
+        "tests": [
+            {
+                "description": "above the minimum is still valid",
+                "data": 1.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 1.1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "minimum validation with signed integer",
+        "schema": {"minimum": -2},
+        "tests": [
+            {
+                "description": "negative above the minimum is valid",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "positive above the minimum is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": -2,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": -3,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/multipleOf.json b/JSON-Schema-Test-Suite/tests/draft4/multipleOf.json
new file mode 100644
index 0000000..ca3b761
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/multipleOf.json
@@ -0,0 +1,60 @@
+[
+    {
+        "description": "by int",
+        "schema": {"multipleOf": 2},
+        "tests": [
+            {
+                "description": "int by int",
+                "data": 10,
+                "valid": true
+            },
+            {
+                "description": "int by int fail",
+                "data": 7,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "by number",
+        "schema": {"multipleOf": 1.5},
+        "tests": [
+            {
+                "description": "zero is multiple of anything",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "4.5 is multiple of 1.5",
+                "data": 4.5,
+                "valid": true
+            },
+            {
+                "description": "35 is not multiple of 1.5",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "by small number",
+        "schema": {"multipleOf": 0.0001},
+        "tests": [
+            {
+                "description": "0.0075 is multiple of 0.0001",
+                "data": 0.0075,
+                "valid": true
+            },
+            {
+                "description": "0.00751 is not multiple of 0.0001",
+                "data": 0.00751,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/not.json b/JSON-Schema-Test-Suite/tests/draft4/not.json
new file mode 100644
index 0000000..cbb7f46
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/not.json
@@ -0,0 +1,96 @@
+[
+    {
+        "description": "not",
+        "schema": {
+            "not": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "allowed",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "disallowed",
+                "data": 1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not multiple types",
+        "schema": {
+            "not": {"type": ["integer", "boolean"]}
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "other mismatch",
+                "data": true,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not more complex schema",
+        "schema": {
+            "not": {
+                "type": "object",
+                "properties": {
+                    "foo": {
+                        "type": "string"
+                    }
+                }
+             }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "other match",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"foo": "bar"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "forbidden property",
+        "schema": {
+            "properties": {
+                "foo": { 
+                    "not": {}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "property present",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "property absent",
+                "data": {"bar": 1, "baz": 2},
+                "valid": true
+            }
+        ]
+    }
+
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/oneOf.json b/JSON-Schema-Test-Suite/tests/draft4/oneOf.json
new file mode 100644
index 0000000..9dfffe1
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/oneOf.json
@@ -0,0 +1,162 @@
+[
+    {
+        "description": "oneOf",
+        "schema": {
+            "oneOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with base schema",
+        "schema": {
+            "type": "string",
+            "oneOf" : [
+                {
+                    "minLength": 2
+                },
+                {
+                    "maxLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one oneOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf complex types",
+        "schema": {
+            "oneOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with empty schema",
+        "schema": {
+            "oneOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "one valid - valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with required",
+        "schema": {
+            "type": "object",
+            "oneOf": [
+                { "required": ["foo", "bar"] },
+                { "required": ["foo", "baz"] }
+            ]
+        },
+        "tests": [
+            {
+                "description": "both invalid - invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "first valid - valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second valid - valid",
+                "data": {"foo": 1, "baz": 3},
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": {"foo": 1, "bar": 2, "baz" : 3},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/optional/bignum.json b/JSON-Schema-Test-Suite/tests/draft4/optional/bignum.json
new file mode 100644
index 0000000..ccc7c17
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/optional/bignum.json
@@ -0,0 +1,107 @@
+[
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a bignum is an integer",
+                "data": 12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a bignum is a number",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a negative bignum is an integer",
+                "data": -12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a negative bignum is a number",
+                "data": -98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "string",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "a bignum is not a string",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"maximum": 18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision",
+        "schema": {
+            "maximum": 972783798187987123879878123.18878137,
+            "exclusiveMaximum": true
+        },
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"minimum": -18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision on negative numbers",
+        "schema": {
+            "minimum": -972783798187987123879878123.18878137,
+            "exclusiveMinimum": true
+        },
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/optional/ecmascript-regex.json b/JSON-Schema-Test-Suite/tests/draft4/optional/ecmascript-regex.json
new file mode 100644
index 0000000..d82e0fe
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/optional/ecmascript-regex.json
@@ -0,0 +1,213 @@
+[
+    {
+        "description": "ECMA 262 regex non-compliance",
+        "schema": { "format": "regex" },
+        "tests": [
+            {
+                "description": "ECMA 262 has no support for \\Z anchor from .NET",
+                "data": "^\\S(|(.|\\n)*\\S)\\Z",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex $ does not match trailing newline",
+        "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+        },
+        "tests": [
+            {
+                "description": "matches in Python, but should not in jsonschema",
+                "data": "abc\n",
+                "valid": false
+            },
+            {
+                "description": "should match",
+                "data": "abc",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex converts \\a to ascii BEL",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\a",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0007",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and upper letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cC",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and lower letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cc",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\d matches ascii digits only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero matches",
+                "data": "0",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO does not match (unlike e.g. Python)",
+                "data": "߀",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) does not match",
+                "data": "\u07c0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\D matches everything but ascii digits",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero does not match",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO matches (unlike e.g. Python)",
+                "data": "߀",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) matches",
+                "data": "\u07c0",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches ascii letters only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' matches",
+                "data": "a",
+                "valid": true
+            },
+            {
+                "description": "latin-1 e-acute does not match (unlike e.g. Python)",
+                "data": "é",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches everything but ascii letters",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' does not match",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "latin-1 e-acute matches (unlike e.g. Python)",
+                "data": "é",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\s matches ascii whitespace only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space matches",
+                "data": " ",
+                "valid": true
+            },
+            {
+                "description": "latin-1 non-breaking-space does not match (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\S matches everything but ascii whitespace",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space does not match",
+                "data": " ",
+                "valid": false
+            },
+            {
+                "description": "latin-1 non-breaking-space matches (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/optional/format.json b/JSON-Schema-Test-Suite/tests/draft4/optional/format.json
new file mode 100644
index 0000000..892404e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/optional/format.json
@@ -0,0 +1,258 @@
+[
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "a valid date-time string",
+                "data": "1963-06-19T08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string without second fraction",
+                "data": "1963-06-19T08:30:06Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with plus offset",
+                "data": "1937-01-01T12:00:27.87+00:20",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with minus offset",
+                "data": "1990-12-31T15:59:50.123-08:00",
+                "valid": true
+            },
+            {
+                "description": "a invalid day in date-time string",
+                "data": "1990-02-31T15:59:60.123-08:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid offset in date-time string",
+                "data": "1990-12-31T15:59:60-24:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963 08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "case-insensitive T and Z",
+                "data": "1963-06-19t08:30:06.283185z",
+                "valid": true
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350T01:01:01",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "a valid URL with anchor tag",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with anchor tag and parantheses",
+                "data": "http://foo.com/blah_(wikipedia)_blah#cite-1",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with URL-encoded stuff",
+                "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff",
+                "valid": true
+            },
+            {
+                "description": "a valid puny-coded URL ",
+                "data": "http://xn--nw2a.xn--j6w193g/",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with many special characters",
+                "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid URL based on IPv4",
+                "data": "http://223.255.255.254",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with ftp scheme",
+                "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL for a simple text file",
+                "data": "http://www.ietf.org/rfc/rfc2396.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL ",
+                "data": "ldap://[2001:db8::7]/c=GB?objectClass?one",
+                "valid": true
+            },
+            {
+                "description": "a valid mailto URI",
+                "data": "mailto:John.Doe@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid newsgroup URI",
+                "data": "news:comp.infosystems.www.servers.unix",
+                "valid": true
+            },
+            {
+                "description": "a valid tel URI",
+                "data": "tel:+1-816-555-1212",
+                "valid": true
+            },
+            {
+                "description": "a valid URN",
+                "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
+                "valid": true
+            },
+            {
+                "description": "an invalid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": false
+            },
+            {
+                "description": "an invalid relative URI Reference",
+                "data": "/abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI though valid URI reference",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces",
+                "data": "http:// shouldfail.com",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces and missing scheme",
+                "data": ":// should fail",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "a valid e-mail address",
+                "data": "joe.bloggs@example.com",
+                "valid": true
+            },
+            {
+                "description": "an invalid e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "a valid IP address",
+                "data": "192.168.0.1",
+                "valid": true
+            },
+            {
+                "description": "an IP address with too many components",
+                "data": "127.0.0.0.1",
+                "valid": false
+            },
+            {
+                "description": "an IP address with out-of-range values",
+                "data": "256.256.256.256",
+                "valid": false
+            },
+            {
+                "description": "an IP address without 4 components",
+                "data": "127.0",
+                "valid": false
+            },
+            {
+                "description": "an IP address as an integer",
+                "data": "0x7f000001",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "a valid IPv6 address",
+                "data": "::1",
+                "valid": true
+            },
+            {
+                "description": "an IPv6 address with out-of-range values",
+                "data": "12345::",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address with too many components",
+                "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address containing illegal characters",
+                "data": "::laptop",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of host names",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "a valid host name",
+                "data": "www.example.com",
+                "valid": true
+            },
+            {
+                "description": "a host name starting with an illegal character",
+                "data": "-a-host-name-that-starts-with--",
+                "valid": false
+            },
+            {
+                "description": "a host name containing illegal characters",
+                "data": "not_a_valid_host_name",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+                "valid": false
+            },
+            {
+                "description": "a host name starting with a digit",
+                "data": "1drv.ms",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/optional/zeroTerminatedFloats.json b/JSON-Schema-Test-Suite/tests/draft4/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..9b50ea2
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+    {
+        "description": "some languages do not distinguish between different types of numeric value",
+        "schema": {
+            "type": "integer"
+        },
+        "tests": [
+            {
+                "description": "a float is not an integer even without fractional part",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/pattern.json b/JSON-Schema-Test-Suite/tests/draft4/pattern.json
new file mode 100644
index 0000000..25e7299
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/pattern.json
@@ -0,0 +1,34 @@
+[
+    {
+        "description": "pattern validation",
+        "schema": {"pattern": "^a*$"},
+        "tests": [
+            {
+                "description": "a matching pattern is valid",
+                "data": "aaa",
+                "valid": true
+            },
+            {
+                "description": "a non-matching pattern is invalid",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": true,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "pattern is not anchored",
+        "schema": {"pattern": "a+"},
+        "tests": [
+            {
+                "description": "matches a substring",
+                "data": "xxaayy",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/patternProperties.json b/JSON-Schema-Test-Suite/tests/draft4/patternProperties.json
new file mode 100644
index 0000000..5f741df
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/patternProperties.json
@@ -0,0 +1,120 @@
+[
+    {
+        "description":
+            "patternProperties validates properties matching a regex",
+        "schema": {
+            "patternProperties": {
+                "f.*o": {"type": "integer"}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "multiple valid matches is valid",
+                "data": {"foo": 1, "foooooo" : 2},
+                "valid": true
+            },
+            {
+                "description": "a single invalid match is invalid",
+                "data": {"foo": "bar", "fooooo": 2},
+                "valid": false
+            },
+            {
+                "description": "multiple invalid matches is invalid",
+                "data": {"foo": "bar", "foooooo" : "baz"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple simultaneous patternProperties are validated",
+        "schema": {
+            "patternProperties": {
+                "a*": {"type": "integer"},
+                "aaa*": {"maximum": 20}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"a": 21},
+                "valid": true
+            },
+            {
+                "description": "a simultaneous match is valid",
+                "data": {"aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "multiple matches is valid",
+                "data": {"a": 21, "aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "an invalid due to one is invalid",
+                "data": {"a": "bar"},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to the other is invalid",
+                "data": {"aaaa": 31},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to both is invalid",
+                "data": {"aaa": "foo", "aaaa": 31},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "regexes are not anchored by default and are case sensitive",
+        "schema": {
+            "patternProperties": {
+                "[0-9]{2,}": { "type": "boolean" },
+                "X_": { "type": "string" }
+            }
+        },
+        "tests": [
+            {
+                "description": "non recognized members are ignored",
+                "data": { "answer 1": "42" },
+                "valid": true
+            },
+            {
+                "description": "recognized members are accounted for",
+                "data": { "a31b": null },
+                "valid": false
+            },
+            {
+                "description": "regexes are case sensitive",
+                "data": { "a_x_3": 3 },
+                "valid": true
+            },
+            {
+                "description": "regexes are case sensitive, 2",
+                "data": { "a_X_3": 3 },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/properties.json b/JSON-Schema-Test-Suite/tests/draft4/properties.json
new file mode 100644
index 0000000..688527b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/properties.json
@@ -0,0 +1,136 @@
+[
+    {
+        "description": "object properties validation",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "both properties present and valid is valid",
+                "data": {"foo": 1, "bar": "baz"},
+                "valid": true
+            },
+            {
+                "description": "one property invalid is invalid",
+                "data": {"foo": 1, "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "both properties invalid is invalid",
+                "data": {"foo": [], "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "doesn't invalidate other properties",
+                "data": {"quux": []},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description":
+            "properties, patternProperties, additionalProperties interaction",
+        "schema": {
+            "properties": {
+                "foo": {"type": "array", "maxItems": 3},
+                "bar": {"type": "array"}
+            },
+            "patternProperties": {"f.o": {"minItems": 2}},
+            "additionalProperties": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "property validates property",
+                "data": {"foo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "property invalidates property",
+                "data": {"foo": [1, 2, 3, 4]},
+                "valid": false
+            },
+            {
+                "description": "patternProperty invalidates property",
+                "data": {"foo": []},
+                "valid": false
+            },
+            {
+                "description": "patternProperty validates nonproperty",
+                "data": {"fxo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "patternProperty invalidates nonproperty",
+                "data": {"fxo": []},
+                "valid": false
+            },
+            {
+                "description": "additionalProperty ignores property",
+                "data": {"bar": []},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty validates others",
+                "data": {"quux": 3},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty invalidates others",
+                "data": {"quux": "foo"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with escaped characters",
+        "schema": {
+            "properties": {
+                "foo\nbar": {"type": "number"},
+                "foo\"bar": {"type": "number"},
+                "foo\\bar": {"type": "number"},
+                "foo\rbar": {"type": "number"},
+                "foo\tbar": {"type": "number"},
+                "foo\fbar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with all numbers is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1",
+                    "foo\\bar": "1",
+                    "foo\rbar": "1",
+                    "foo\tbar": "1",
+                    "foo\fbar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/ref.json b/JSON-Schema-Test-Suite/tests/draft4/ref.json
new file mode 100644
index 0000000..51e750f
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/ref.json
@@ -0,0 +1,411 @@
+[
+    {
+        "description": "root pointer ref",
+        "schema": {
+            "properties": {
+                "foo": {"$ref": "#"}
+            },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"foo": false},
+                "valid": true
+            },
+            {
+                "description": "recursive match",
+                "data": {"foo": {"foo": false}},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": false},
+                "valid": false
+            },
+            {
+                "description": "recursive mismatch",
+                "data": {"foo": {"bar": false}},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to object",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"$ref": "#/properties/foo"}
+            }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"bar": 3},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": true},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to array",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"$ref": "#/items/0"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "match array",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "mismatch array",
+                "data": [1, "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "escaped pointer ref",
+        "schema": {
+            "tilda~field": {"type": "integer"},
+            "slash/field": {"type": "integer"},
+            "percent%field": {"type": "integer"},
+            "properties": {
+                "tilda": {"$ref": "#/tilda~0field"},
+                "slash": {"$ref": "#/slash~1field"},
+                "percent": {"$ref": "#/percent%25field"}
+            }
+        },
+        "tests": [
+            {
+                "description": "slash invalid",
+                "data": {"slash": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "tilda invalid",
+                "data": {"tilda": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "percent invalid",
+                "data": {"percent": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "slash valid",
+                "data": {"slash": 123},
+                "valid": true
+            },
+            {
+                "description": "tilda valid",
+                "data": {"tilda": 123},
+                "valid": true
+            },
+            {
+                "description": "percent valid",
+                "data": {"percent": 123},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested refs",
+        "schema": {
+            "definitions": {
+                "a": {"type": "integer"},
+                "b": {"$ref": "#/definitions/a"},
+                "c": {"$ref": "#/definitions/b"}
+            },
+            "$ref": "#/definitions/c"
+        },
+        "tests": [
+            {
+                "description": "nested ref valid",
+                "data": 5,
+                "valid": true
+            },
+            {
+                "description": "nested ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref overrides any sibling keywords",
+        "schema": {
+            "definitions": {
+                "reffed": {
+                    "type": "array"
+                }
+            },
+            "properties": {
+                "foo": {
+                    "$ref": "#/definitions/reffed",
+                    "maxItems": 2
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "ref valid",
+                "data": { "foo": [] },
+                "valid": true
+            },
+            {
+                "description": "ref valid, maxItems ignored",
+                "data": { "foo": [ 1, 2, 3] },
+                "valid": true
+            },
+            {
+                "description": "ref invalid",
+                "data": { "foo": "string" },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "remote ref, containing refs itself",
+        "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": {"minLength": 1},
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": {"minLength": -1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "property named $ref that is not a reference",
+        "schema": {
+            "properties": {
+                "$ref": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "property named $ref valid",
+                "data": {"$ref": "a"},
+                "valid": true
+            },
+            {
+                "description": "property named $ref invalid",
+                "data": {"$ref": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Recursive references between schemas",
+        "schema": {
+            "id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+                "meta": {"type": "string"},
+                "nodes": {
+                    "type": "array",
+                    "items": {"$ref": "node"}
+                }
+            },
+            "required": ["meta", "nodes"],
+            "definitions": {
+                "node": {
+                    "id": "http://localhost:1234/node",
+                    "description": "node",
+                    "type": "object",
+                    "properties": {
+                        "value": {"type": "number"},
+                        "subtree": {"$ref": "tree"}
+                    },
+                    "required": ["value"]
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 1.1},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": "string is invalid"},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "refs with quote",
+        "schema": {
+            "properties": {
+                "foo\"bar": {"$ref": "#/definitions/foo%22bar"}
+            },
+            "definitions": {
+                "foo\"bar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with numbers is valid",
+                "data": {
+                    "foo\"bar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier",
+        "schema": {
+            "allOf": [{
+                "$ref": "#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "id": "#foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with absolute URI",
+        "schema": {
+            "allOf": [{
+                "$ref": "http://localhost:1234/bar#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "id": "http://localhost:1234/bar#foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with base URI change in subschema",
+        "schema": {
+            "id": "http://localhost:1234/root",
+            "allOf": [{
+                "$ref": "http://localhost:1234/nested.json#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "id": "nested.json",
+                    "definitions": {
+                        "B": {
+                            "id": "#foo",
+                            "type": "integer"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/refRemote.json b/JSON-Schema-Test-Suite/tests/draft4/refRemote.json
new file mode 100644
index 0000000..8611fad
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/refRemote.json
@@ -0,0 +1,171 @@
+[
+    {
+        "description": "remote ref",
+        "schema": {"$ref": "http://localhost:1234/integer.json"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "fragment within remote ref",
+        "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},
+        "tests": [
+            {
+                "description": "remote fragment valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote fragment invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref within remote ref",
+        "schema": {
+            "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"
+        },
+        "tests": [
+            {
+                "description": "ref within ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "ref within ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change",
+        "schema": {
+            "id": "http://localhost:1234/",
+            "items": {
+                "id": "folder/",
+                "items": {"$ref": "folderInteger.json"}
+            }
+        },
+        "tests": [
+            {
+                "description": "base URI change ref valid",
+                "data": [[1]],
+                "valid": true
+            },
+            {
+                "description": "base URI change ref invalid",
+                "data": [["a"]],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder",
+        "schema": {
+            "id": "http://localhost:1234/scope_change_defs1.json",
+            "type" : "object",
+            "properties": {
+                "list": {"$ref": "#/definitions/baz"}
+            },
+            "definitions": {
+                "baz": {
+                    "id": "folder/",
+                    "type": "array",
+                    "items": {"$ref": "folderInteger.json"}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder in subschema",
+        "schema": {
+            "id": "http://localhost:1234/scope_change_defs2.json",
+            "type" : "object",
+            "properties": {
+                "list": {"$ref": "#/definitions/baz/definitions/bar"}
+            },
+            "definitions": {
+                "baz": {
+                    "id": "folder/",
+                    "definitions": {
+                        "bar": {
+                            "type": "array",
+                            "items": {"$ref": "folderInteger.json"}
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "root ref in remote ref",
+        "schema": {
+            "id": "http://localhost:1234/object",
+            "type": "object",
+            "properties": {
+                "name": {"$ref": "name.json#/definitions/orNull"}
+            }
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": {
+                    "name": "foo"
+                },
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": {
+                    "name": null
+                },
+                "valid": true
+            },
+            {
+                "description": "object is invalid",
+                "data": {
+                    "name": {
+                        "name": null
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/required.json b/JSON-Schema-Test-Suite/tests/draft4/required.json
new file mode 100644
index 0000000..9b05318
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/required.json
@@ -0,0 +1,89 @@
+[
+    {
+        "description": "required validation",
+        "schema": {
+            "properties": {
+                "foo": {},
+                "bar": {}
+            },
+            "required": ["foo"]
+        },
+        "tests": [
+            {
+                "description": "present required property is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "non-present required property is invalid",
+                "data": {"bar": 1},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required default validation",
+        "schema": {
+            "properties": {
+                "foo": {}
+            }
+        },
+        "tests": [
+            {
+                "description": "not required by default",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with escaped characters",
+        "schema": {
+            "required": [
+                "foo\nbar",
+                "foo\"bar",
+                "foo\\bar",
+                "foo\rbar",
+                "foo\tbar",
+                "foo\fbar"
+            ]
+        },
+        "tests": [
+            {
+                "description": "object with all properties present is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with some properties missing is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/type.json b/JSON-Schema-Test-Suite/tests/draft4/type.json
new file mode 100644
index 0000000..ea33b18
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/type.json
@@ -0,0 +1,464 @@
+[
+    {
+        "description": "integer type matches integers",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "an integer is an integer",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is not an integer",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an integer",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not an integer, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not an integer",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not an integer",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an integer",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an integer",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "number type matches numbers",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "an integer is a number",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is a number",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "a string is not a number",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not a number, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not a number",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a number",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a number",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a number",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "string type matches strings",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "1 is not a string",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not a string",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is a string",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a string is still a string, even if it looks like a number",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "an empty string is still a string",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "an object is not a string",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a string",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a string",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a string",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "object type matches objects",
+        "schema": {"type": "object"},
+        "tests": [
+            {
+                "description": "an integer is not an object",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an object",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an object",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is an object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "an array is not an object",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an object",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an object",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "array type matches arrays",
+        "schema": {"type": "array"},
+        "tests": [
+            {
+                "description": "an integer is not an array",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an array",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an array",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not an array",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is an array",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "a boolean is not an array",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an array",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "boolean type matches booleans",
+        "schema": {"type": "boolean"},
+        "tests": [
+            {
+                "description": "an integer is not a boolean",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "zero is not a boolean",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a float is not a boolean",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not a boolean",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not a boolean",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not a boolean",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a boolean",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is a boolean",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "false is a boolean",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is not a boolean",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "null type matches only the null object",
+        "schema": {"type": "null"},
+        "tests": [
+            {
+                "description": "an integer is not null",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not null",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "zero is not null",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a string is not null",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not null",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not null",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not null",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is not null",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "false is not null",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple types can be specified in an array",
+        "schema": {"type": ["integer", "string"]},
+        "tests": [
+            {
+                "description": "an integer is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a float is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "an object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type as array with one item",
+        "schema": {
+            "type": ["string"]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array or object",
+        "schema": {
+            "type": ["array", "object"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array, object or null",
+        "schema": {
+            "type": ["array", "object", "null"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json b/JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json
new file mode 100644
index 0000000..d312ad7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json
@@ -0,0 +1,173 @@
+[
+    {
+        "description": "uniqueItems validation",
+        "schema": {"uniqueItems": true},
+        "tests": [
+            {
+                "description": "unique array of integers is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of integers is invalid",
+                "data": [1, 1],
+                "valid": false
+            },
+            {
+                "description": "numbers are unique if mathematically unequal",
+                "data": [1.0, 1.00, 1],
+                "valid": false
+            },
+            {
+                "description": "false is not equal to zero",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "true is not equal to one",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "unique array of objects is valid",
+                "data": [{"foo": "bar"}, {"foo": "baz"}],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of objects is invalid",
+                "data": [{"foo": "bar"}, {"foo": "bar"}],
+                "valid": false
+            },
+            {
+                "description": "unique array of nested objects is valid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : false}}}
+                ],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of nested objects is invalid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : true}}}
+                ],
+                "valid": false
+            },
+            {
+                "description": "unique array of arrays is valid",
+                "data": [["foo"], ["bar"]],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of arrays is invalid",
+                "data": [["foo"], ["foo"]],
+                "valid": false
+            },
+            {
+                "description": "1 and true are unique",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "0 and false are unique",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "unique heterogeneous types are valid",
+                "data": [{}, [1], true, null, 1],
+                "valid": true
+            },
+            {
+                "description": "non-unique heterogeneous types are invalid",
+                "data": [{}, [1], true, null, {}, 1],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "unique array extended from [false, true] is valid",
+                "data": [false, true, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "unique array extended from [true, false] is valid",
+                "data": [true, false, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "non-unique array extended from [false, true] is not valid",
+                "data": [false, true, "foo", "foo"],
+                "valid": false
+            },
+            {
+                "description": "non-unique array extended from [true, false] is not valid",
+                "data": [true, false, "foo", "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items and additionalItems=false",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true, 
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "extra items are invalid even if unique",
+                "data": [false, true, null],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/additionalItems.json b/JSON-Schema-Test-Suite/tests/draft6/additionalItems.json
new file mode 100644
index 0000000..abecc57
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/additionalItems.json
@@ -0,0 +1,87 @@
+[
+    {
+        "description": "additionalItems as schema",
+        "schema": {
+            "items": [{}],
+            "additionalItems": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "additional items match schema",
+                "data": [ null, 2, 3, 4 ],
+                "valid": true
+            },
+            {
+                "description": "additional items do not match schema",
+                "data": [ null, 2, 3, "foo" ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "items is schema, no additionalItems",
+        "schema": {
+            "items": {},
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "all items match schema",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "array of items with no additionalItems",
+        "schema": {
+            "items": [{}, {}, {}],
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "fewer number of items present",
+                "data": [ 1, 2 ],
+                "valid": true
+            },
+            {
+                "description": "equal number of items present",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "additional items are not permitted",
+                "data": [ 1, 2, 3, 4 ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalItems as false without items",
+        "schema": {"additionalItems": false},
+        "tests": [
+            {
+                "description":
+                    "items defaults to empty schema so everything is valid",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalItems are allowed by default",
+        "schema": {"items": [{"type": "integer"}]},
+        "tests": [
+            {
+                "description": "only the first item is validated",
+                "data": [1, "foo", false],
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/additionalProperties.json b/JSON-Schema-Test-Suite/tests/draft6/additionalProperties.json
new file mode 100644
index 0000000..ffeac6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/additionalProperties.json
@@ -0,0 +1,133 @@
+[
+    {
+        "description":
+            "additionalProperties being false does not allow other properties",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "patternProperties": { "^v": {} },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobarbaz",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "patternProperties are not additional properties",
+                "data": {"foo":1, "vroom": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "non-ASCII pattern with additionalProperties",
+        "schema": {
+            "patternProperties": {"^á": {}},
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "matching the pattern is valid",
+                "data": {"ármányos": 2},
+                "valid": true
+            },
+            {
+                "description": "not matching the pattern is invalid",
+                "data": {"élmény": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties allows a schema which should validate",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : 12},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties can exist by itself",
+        "schema": {
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties are allowed by default",
+        "schema": {"properties": {"foo": {}, "bar": {}}},
+        "tests": [
+            {
+                "description": "additional properties are allowed",
+                "data": {"foo": 1, "bar": 2, "quux": true},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties should not look in applicators",
+        "schema": {
+            "allOf": [
+                {"properties": {"foo": {}}}
+            ],
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "properties defined in allOf are not allowed",
+                "data": {"foo": 1, "bar": true},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/allOf.json b/JSON-Schema-Test-Suite/tests/draft6/allOf.json
new file mode 100644
index 0000000..eb61209
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/allOf.json
@@ -0,0 +1,218 @@
+[
+    {
+        "description": "allOf",
+        "schema": {
+            "allOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "allOf",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "mismatch second",
+                "data": {"foo": "baz"},
+                "valid": false
+            },
+            {
+                "description": "mismatch first",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "baz", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with base schema",
+        "schema": {
+            "properties": {"bar": {"type": "integer"}},
+            "required": ["bar"],
+            "allOf" : [
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                },
+                {
+                    "properties": {
+                        "baz": {"type": "null"}
+                    },
+                    "required": ["baz"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": "quux", "bar": 2, "baz": null},
+                "valid": true
+            },
+            {
+                "description": "mismatch base schema",
+                "data": {"foo": "quux", "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch first allOf",
+                "data": {"bar": 2, "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch second allOf",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "mismatch both",
+                "data": {"bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf simple types",
+        "schema": {
+            "allOf": [
+                {"maximum": 30},
+                {"minimum": 20}
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": 25,
+                "valid": true
+            },
+            {
+                "description": "mismatch one",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, all true",
+        "schema": {"allOf": [true, true]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, some false",
+        "schema": {"allOf": [true, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, all false",
+        "schema": {"allOf": [false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with one empty schema",
+        "schema": {
+            "allOf": [
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with two empty schemas",
+        "schema": {
+            "allOf": [
+                {},
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with the first empty schema",
+        "schema": {
+            "allOf": [
+                {},
+                { "type": "number" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with the last empty schema",
+        "schema": {
+            "allOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/anyOf.json b/JSON-Schema-Test-Suite/tests/draft6/anyOf.json
new file mode 100644
index 0000000..ab5eb38
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/anyOf.json
@@ -0,0 +1,189 @@
+[
+    {
+        "description": "anyOf",
+        "schema": {
+            "anyOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid",
+                "data": 3,
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with base schema",
+        "schema": {
+            "type": "string",
+            "anyOf" : [
+                {
+                    "maxLength": 2
+                },
+                {
+                    "minLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one anyOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both anyOf invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, all true",
+        "schema": {"anyOf": [true, true]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, some true",
+        "schema": {"anyOf": [true, false]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, all false",
+        "schema": {"anyOf": [false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf complex types",
+        "schema": {
+            "anyOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with one empty schema",
+        "schema": {
+            "anyOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is valid",
+                "data": 123,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested anyOf, to check validation semantics",
+        "schema": {
+            "anyOf": [
+                {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        }
+                    ]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "anything non-null is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/boolean_schema.json b/JSON-Schema-Test-Suite/tests/draft6/boolean_schema.json
new file mode 100644
index 0000000..6d40f23
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/boolean_schema.json
@@ -0,0 +1,104 @@
+[
+    {
+        "description": "boolean schema 'true'",
+        "schema": true,
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "boolean true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "boolean false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": "bar"},
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "array is valid",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "boolean schema 'false'",
+        "schema": false,
+        "tests": [
+            {
+                "description": "number is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "boolean true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "boolean false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "object is invalid",
+                "data": {"foo": "bar"},
+                "valid": false
+            },
+            {
+                "description": "empty object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "array is invalid",
+                "data": ["foo"],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/const.json b/JSON-Schema-Test-Suite/tests/draft6/const.json
new file mode 100644
index 0000000..c089625
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/const.json
@@ -0,0 +1,170 @@
+[
+    {
+        "description": "const validation",
+        "schema": {"const": 2},
+        "tests": [
+            {
+                "description": "same value is valid",
+                "data": 2,
+                "valid": true
+            },
+            {
+                "description": "another value is invalid",
+                "data": 5,
+                "valid": false
+            },
+            {
+                "description": "another type is invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with object",
+        "schema": {"const": {"foo": "bar", "baz": "bax"}},
+        "tests": [
+            {
+                "description": "same object is valid",
+                "data": {"foo": "bar", "baz": "bax"},
+                "valid": true
+            },
+            {
+                "description": "same object with different property order is valid",
+                "data": {"baz": "bax", "foo": "bar"},
+                "valid": true
+            },
+            {
+                "description": "another object is invalid",
+                "data": {"foo": "bar"},
+                "valid": false
+            },
+            {
+                "description": "another type is invalid",
+                "data": [1, 2],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with array",
+        "schema": {"const": [{ "foo": "bar" }]},
+        "tests": [
+            {
+                "description": "same array is valid",
+                "data": [{"foo": "bar"}],
+                "valid": true
+            },
+            {
+                "description": "another array item is invalid",
+                "data": [2],
+                "valid": false
+            },
+            {
+                "description": "array with additional items is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with null",
+        "schema": {"const": null},
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "not null is invalid",
+                "data": 0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with false does not match 0",
+        "schema": {"const": false},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with true does not match 1",
+        "schema": {"const": true},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with 0 does not match false",
+        "schema": {"const": 0},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "const with 1 does not match true",
+        "schema": {"const": 1},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/contains.json b/JSON-Schema-Test-Suite/tests/draft6/contains.json
new file mode 100644
index 0000000..67ecbd9
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/contains.json
@@ -0,0 +1,100 @@
+[
+    {
+        "description": "contains keyword validation",
+        "schema": {
+            "contains": {"minimum": 5}
+        },
+        "tests": [
+            {
+                "description": "array with item matching schema (5) is valid",
+                "data": [3, 4, 5],
+                "valid": true
+            },
+            {
+                "description": "array with item matching schema (6) is valid",
+                "data": [3, 4, 6],
+                "valid": true
+            },
+            {
+                "description": "array with two items matching schema (5, 6) is valid",
+                "data": [3, 4, 5, 6],
+                "valid": true
+            },
+            {
+                "description": "array without items matching schema is invalid",
+                "data": [2, 3, 4],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "not array is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with const keyword",
+        "schema": {
+            "contains": { "const": 5 }
+        },
+        "tests": [
+            {
+                "description": "array with item 5 is valid",
+                "data": [3, 4, 5],
+                "valid": true
+            },
+            {
+                "description": "array with two items 5 is valid",
+                "data": [3, 4, 5, 5],
+                "valid": true
+            },
+            {
+                "description": "array without item 5 is invalid",
+                "data": [1, 2, 3, 4],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with boolean schema true",
+        "schema": {"contains": true},
+        "tests": [
+            {
+                "description": "any non-empty array is valid",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with boolean schema false",
+        "schema": {"contains": false},
+        "tests": [
+            {
+                "description": "any non-empty array is invalid",
+                "data": ["foo"],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "non-arrays are valid",
+                "data": "contains does not apply to strings",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/default.json b/JSON-Schema-Test-Suite/tests/draft6/default.json
new file mode 100644
index 0000000..1762977
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/default.json
@@ -0,0 +1,49 @@
+[
+    {
+        "description": "invalid type for default",
+        "schema": {
+            "properties": {
+                "foo": {
+                    "type": "integer",
+                    "default": []
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"foo": 13},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid string value for default",
+        "schema": {
+            "properties": {
+                "bar": {
+                    "type": "string",
+                    "minLength": 4,
+                    "default": "bad"
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"bar": "good"},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/definitions.json b/JSON-Schema-Test-Suite/tests/draft6/definitions.json
new file mode 100644
index 0000000..7f3b899
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/definitions.json
@@ -0,0 +1,32 @@
+[
+    {
+        "description": "valid definition",
+        "schema": {"$ref": "http://json-schema.org/draft-06/schema#"},
+        "tests": [
+            {
+                "description": "valid definition schema",
+                "data": {
+                    "definitions": {
+                        "foo": {"type": "integer"}
+                    }
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid definition",
+        "schema": {"$ref": "http://json-schema.org/draft-06/schema#"},
+        "tests": [
+            {
+                "description": "invalid definition schema",
+                "data": {
+                    "definitions": {
+                        "foo": {"type": 1}
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/dependencies.json b/JSON-Schema-Test-Suite/tests/draft6/dependencies.json
new file mode 100644
index 0000000..8dd78aa
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/dependencies.json
@@ -0,0 +1,268 @@
+[
+    {
+        "description": "dependencies",
+        "schema": {
+            "dependencies": {"bar": ["foo"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependant",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "with dependency",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["bar"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "dependencies with empty array",
+        "schema": {
+            "dependencies": {"bar": []}
+        },
+        "tests": [
+            {
+                "description": "empty object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "object with one property",
+                "data": {"bar": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies",
+        "schema": {
+            "dependencies": {"quux": ["foo", "bar"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependants",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "with dependencies",
+                "data": {"foo": 1, "bar": 2, "quux": 3},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"foo": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing other dependency",
+                "data": {"bar": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing both dependencies",
+                "data": {"quux": 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies subschema",
+        "schema": {
+            "dependencies": {
+                "bar": {
+                    "properties": {
+                        "foo": {"type": "integer"},
+                        "bar": {"type": "integer"}
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "no dependency",
+                "data": {"foo": "quux"},
+                "valid": true
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type other",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            },
+            {
+                "description": "wrong type both",
+                "data": {"foo": "quux", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "dependencies with boolean subschemas",
+        "schema": {
+            "dependencies": {
+                "foo": true,
+                "bar": false
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property having schema true is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "object with property having schema false is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "object with both properties is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "empty array of dependencies",
+        "schema": {
+            "dependencies": {
+                "foo": []
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property is valid",
+                "data": { "foo": 1 },
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "non-object is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "dependencies with escaped characters",
+        "schema": {
+            "dependencies": {
+                "foo\nbar": ["foo\rbar"],
+                "foo\tbar": {
+                    "minProperties": 4
+                },
+                "foo'bar": {"required": ["foo\"bar"]},
+                "foo\"bar": ["foo'bar"]
+            }
+        },
+        "tests": [
+            {
+                "description": "valid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\rbar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2,
+                    "b": 3,
+                    "c": 4
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 3",
+                "data": {
+                    "foo'bar": 1,
+                    "foo\"bar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 3",
+                "data": {
+                    "foo'bar": 1
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 4",
+                "data": {
+                    "foo\"bar": 2
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/enum.json b/JSON-Schema-Test-Suite/tests/draft6/enum.json
new file mode 100644
index 0000000..32d7902
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/enum.json
@@ -0,0 +1,179 @@
+[
+    {
+        "description": "simple enum validation",
+        "schema": {"enum": [1, 2, 3]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": 4,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "heterogeneous enum validation",
+        "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "objects are deep compared",
+                "data": {"foo": false},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enums in properties",
+        "schema": {
+            "type":"object",
+            "properties": {
+                "foo": {"enum":["foo"]},
+                "bar": {"enum":["bar"]}
+            },
+            "required": ["bar"]
+        },
+        "tests": [
+            {
+                "description": "both properties are valid",
+                "data": {"foo":"foo", "bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing optional property is valid",
+                "data": {"bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing required property is invalid",
+                "data": {"foo":"foo"},
+                "valid": false
+            },
+            {
+                "description": "missing all properties is invalid",
+                "data": {},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with escaped characters",
+        "schema": {
+            "enum": ["foo\nbar", "foo\rbar"]
+        },
+        "tests": [
+            {
+                "description": "member 1 is valid",
+                "data": "foo\nbar",
+                "valid": true
+            },
+            {
+                "description": "member 2 is valid",
+                "data": "foo\rbar",
+                "valid": true
+            },
+            {
+                "description": "another string is invalid",
+                "data": "abc",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with false does not match 0",
+        "schema": {"enum": [false]},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with true does not match 1",
+        "schema": {"enum": [true]},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with 0 does not match false",
+        "schema": {"enum": [0]},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "enum with 1 does not match true",
+        "schema": {"enum": [1]},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/exclusiveMaximum.json b/JSON-Schema-Test-Suite/tests/draft6/exclusiveMaximum.json
new file mode 100644
index 0000000..dc3cd70
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/exclusiveMaximum.json
@@ -0,0 +1,30 @@
+[
+    {
+        "description": "exclusiveMaximum validation",
+        "schema": {
+            "exclusiveMaximum": 3.0
+        },
+        "tests": [
+            {
+                "description": "below the exclusiveMaximum is valid",
+                "data": 2.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 3.0,
+                "valid": false
+            },
+            {
+                "description": "above the exclusiveMaximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/exclusiveMinimum.json b/JSON-Schema-Test-Suite/tests/draft6/exclusiveMinimum.json
new file mode 100644
index 0000000..b38d7ec
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/exclusiveMinimum.json
@@ -0,0 +1,30 @@
+[
+    {
+        "description": "exclusiveMinimum validation",
+        "schema": {
+            "exclusiveMinimum": 1.1
+        },
+        "tests": [
+            {
+                "description": "above the exclusiveMinimum is valid",
+                "data": 1.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "below the exclusiveMinimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/format.json b/JSON-Schema-Test-Suite/tests/draft6/format.json
new file mode 100644
index 0000000..32e8152
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/format.json
@@ -0,0 +1,326 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of hostnames",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of JSON pointers",
+        "schema": {"format": "json-pointer"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URI references",
+        "schema": {"format": "uri-reference"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URI templates",
+        "schema": {"format": "uri-template"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/items.json b/JSON-Schema-Test-Suite/tests/draft6/items.json
new file mode 100644
index 0000000..67f1184
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/items.json
@@ -0,0 +1,250 @@
+[
+    {
+        "description": "a schema given for items",
+        "schema": {
+            "items": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "wrong type of items",
+                "data": [1, "x"],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "length": 1
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "an array of schemas for items",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"type": "string"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "correct types",
+                "data": [ 1, "foo" ],
+                "valid": true
+            },
+            {
+                "description": "wrong types",
+                "data": [ "foo", 1 ],
+                "valid": false
+            },
+            {
+                "description": "incomplete array of items",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with additional items",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array",
+                "data": [ ],
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "1": "valid",
+                    "length": 2
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schema (true)",
+        "schema": {"items": true},
+        "tests": [
+            {
+                "description": "any array is valid",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schema (false)",
+        "schema": {"items": false},
+        "tests": [
+            {
+                "description": "any non-empty array is invalid",
+                "data": [ 1, "foo", true ],
+                "valid": false
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schemas",
+        "schema": {
+            "items": [true, false]
+        },
+        "tests": [
+            {
+                "description": "array with one item is valid",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with two items is invalid",
+                "data": [ 1, "foo" ],
+                "valid": false
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items and subitems",
+        "schema": {
+            "definitions": {
+                "item": {
+                    "type": "array",
+                    "additionalItems": false,
+                    "items": [
+                        { "$ref": "#/definitions/sub-item" },
+                        { "$ref": "#/definitions/sub-item" }
+                    ]
+                },
+                "sub-item": {
+                    "type": "object",
+                    "required": ["foo"]
+                }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+                { "$ref": "#/definitions/item" },
+                { "$ref": "#/definitions/item" },
+                { "$ref": "#/definitions/item" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": true
+            },
+            {
+                "description": "too many items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "too many sub-items",
+                "data": [
+                    [ {"foo": null}, {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong item",
+                "data": [
+                    {"foo": null},
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong sub-item",
+                "data": [
+                    [ {}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "fewer items is valid",
+                "data": [
+                    [ {"foo": null} ],
+                    [ {"foo": null} ]
+                ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested items",
+        "schema": {
+            "type": "array",
+            "items": {
+                "type": "array",
+                "items": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {
+                            "type": "number"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid nested array",
+                "data": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": true
+            },
+            {
+                "description": "nested array with invalid type",
+                "data": [[[["1"]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": false
+            },
+            {
+                "description": "not deep enough",
+                "data": [[[1], [2],[3]], [[4], [5], [6]]],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/maxItems.json b/JSON-Schema-Test-Suite/tests/draft6/maxItems.json
new file mode 100644
index 0000000..3b53a6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/maxItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maxItems validation",
+        "schema": {"maxItems": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "foobar",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/maxLength.json b/JSON-Schema-Test-Suite/tests/draft6/maxLength.json
new file mode 100644
index 0000000..811d35b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/maxLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "maxLength validation",
+        "schema": {"maxLength": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": "f",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            },
+            {
+                "description": "two supplementary Unicode code points is long enough",
+                "data": "\uD83D\uDCA9\uD83D\uDCA9",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/maxProperties.json b/JSON-Schema-Test-Suite/tests/draft6/maxProperties.json
new file mode 100644
index 0000000..513731e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/maxProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "maxProperties validation",
+        "schema": {"maxProperties": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": {"foo": 1, "bar": 2, "baz": 3},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/maximum.json b/JSON-Schema-Test-Suite/tests/draft6/maximum.json
new file mode 100644
index 0000000..8150984
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/maximum.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maximum validation",
+        "schema": {"maximum": 3.0},
+        "tests": [
+            {
+                "description": "below the maximum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 3.0,
+                "valid": true
+            },
+            {
+                "description": "above the maximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/minItems.json b/JSON-Schema-Test-Suite/tests/draft6/minItems.json
new file mode 100644
index 0000000..ed51188
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/minItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "minItems validation",
+        "schema": {"minItems": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/minLength.json b/JSON-Schema-Test-Suite/tests/draft6/minLength.json
new file mode 100644
index 0000000..3f09158
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/minLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "minLength validation",
+        "schema": {"minLength": 2},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": "f",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "one supplementary Unicode code point is not long enough",
+                "data": "\uD83D\uDCA9",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/minProperties.json b/JSON-Schema-Test-Suite/tests/draft6/minProperties.json
new file mode 100644
index 0000000..49a0726
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/minProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "minProperties validation",
+        "schema": {"minProperties": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/minimum.json b/JSON-Schema-Test-Suite/tests/draft6/minimum.json
new file mode 100644
index 0000000..2a9c42b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/minimum.json
@@ -0,0 +1,59 @@
+[
+    {
+        "description": "minimum validation",
+        "schema": {"minimum": 1.1},
+        "tests": [
+            {
+                "description": "above the minimum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "minimum validation with signed integer",
+        "schema": {"minimum": -2},
+        "tests": [
+            {
+                "description": "negative above the minimum is valid",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "positive above the minimum is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": -2,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": -3,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/multipleOf.json b/JSON-Schema-Test-Suite/tests/draft6/multipleOf.json
new file mode 100644
index 0000000..ca3b761
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/multipleOf.json
@@ -0,0 +1,60 @@
+[
+    {
+        "description": "by int",
+        "schema": {"multipleOf": 2},
+        "tests": [
+            {
+                "description": "int by int",
+                "data": 10,
+                "valid": true
+            },
+            {
+                "description": "int by int fail",
+                "data": 7,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "by number",
+        "schema": {"multipleOf": 1.5},
+        "tests": [
+            {
+                "description": "zero is multiple of anything",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "4.5 is multiple of 1.5",
+                "data": 4.5,
+                "valid": true
+            },
+            {
+                "description": "35 is not multiple of 1.5",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "by small number",
+        "schema": {"multipleOf": 0.0001},
+        "tests": [
+            {
+                "description": "0.0075 is multiple of 0.0001",
+                "data": 0.0075,
+                "valid": true
+            },
+            {
+                "description": "0.00751 is not multiple of 0.0001",
+                "data": 0.00751,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/not.json b/JSON-Schema-Test-Suite/tests/draft6/not.json
new file mode 100644
index 0000000..98de0ed
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/not.json
@@ -0,0 +1,117 @@
+[
+    {
+        "description": "not",
+        "schema": {
+            "not": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "allowed",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "disallowed",
+                "data": 1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not multiple types",
+        "schema": {
+            "not": {"type": ["integer", "boolean"]}
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "other mismatch",
+                "data": true,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not more complex schema",
+        "schema": {
+            "not": {
+                "type": "object",
+                "properties": {
+                    "foo": {
+                        "type": "string"
+                    }
+                }
+             }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "other match",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"foo": "bar"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "forbidden property",
+        "schema": {
+            "properties": {
+                "foo": { 
+                    "not": {}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "property present",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "property absent",
+                "data": {"bar": 1, "baz": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "not with boolean schema true",
+        "schema": {"not": true},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not with boolean schema false",
+        "schema": {"not": false},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/oneOf.json b/JSON-Schema-Test-Suite/tests/draft6/oneOf.json
new file mode 100644
index 0000000..57640b7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/oneOf.json
@@ -0,0 +1,206 @@
+[
+    {
+        "description": "oneOf",
+        "schema": {
+            "oneOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with base schema",
+        "schema": {
+            "type": "string",
+            "oneOf" : [
+                {
+                    "minLength": 2
+                },
+                {
+                    "maxLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one oneOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, all true",
+        "schema": {"oneOf": [true, true, true]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, one true",
+        "schema": {"oneOf": [true, false, false]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, more than one true",
+        "schema": {"oneOf": [true, true, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, all false",
+        "schema": {"oneOf": [false, false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf complex types",
+        "schema": {
+            "oneOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with empty schema",
+        "schema": {
+            "oneOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "one valid - valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with required",
+        "schema": {
+            "type": "object",
+            "oneOf": [
+                { "required": ["foo", "bar"] },
+                { "required": ["foo", "baz"] }
+            ]
+        },
+        "tests": [
+            {
+                "description": "both invalid - invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "first valid - valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second valid - valid",
+                "data": {"foo": 1, "baz": 3},
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": {"foo": 1, "bar": 2, "baz" : 3},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/optional/bignum.json b/JSON-Schema-Test-Suite/tests/draft6/optional/bignum.json
new file mode 100644
index 0000000..fac275e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/optional/bignum.json
@@ -0,0 +1,105 @@
+[
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a bignum is an integer",
+                "data": 12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a bignum is a number",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a negative bignum is an integer",
+                "data": -12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a negative bignum is a number",
+                "data": -98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "string",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "a bignum is not a string",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"maximum": 18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision",
+        "schema": {
+            "exclusiveMaximum": 972783798187987123879878123.18878137
+        },
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"minimum": -18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision on negative numbers",
+        "schema": {
+            "exclusiveMinimum": -972783798187987123879878123.18878137
+        },
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/optional/ecmascript-regex.json b/JSON-Schema-Test-Suite/tests/draft6/optional/ecmascript-regex.json
new file mode 100644
index 0000000..d82e0fe
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/optional/ecmascript-regex.json
@@ -0,0 +1,213 @@
+[
+    {
+        "description": "ECMA 262 regex non-compliance",
+        "schema": { "format": "regex" },
+        "tests": [
+            {
+                "description": "ECMA 262 has no support for \\Z anchor from .NET",
+                "data": "^\\S(|(.|\\n)*\\S)\\Z",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex $ does not match trailing newline",
+        "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+        },
+        "tests": [
+            {
+                "description": "matches in Python, but should not in jsonschema",
+                "data": "abc\n",
+                "valid": false
+            },
+            {
+                "description": "should match",
+                "data": "abc",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex converts \\a to ascii BEL",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\a",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0007",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and upper letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cC",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and lower letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cc",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\d matches ascii digits only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero matches",
+                "data": "0",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO does not match (unlike e.g. Python)",
+                "data": "߀",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) does not match",
+                "data": "\u07c0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\D matches everything but ascii digits",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero does not match",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO matches (unlike e.g. Python)",
+                "data": "߀",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) matches",
+                "data": "\u07c0",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches ascii letters only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' matches",
+                "data": "a",
+                "valid": true
+            },
+            {
+                "description": "latin-1 e-acute does not match (unlike e.g. Python)",
+                "data": "é",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches everything but ascii letters",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' does not match",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "latin-1 e-acute matches (unlike e.g. Python)",
+                "data": "é",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\s matches ascii whitespace only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space matches",
+                "data": " ",
+                "valid": true
+            },
+            {
+                "description": "latin-1 non-breaking-space does not match (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\S matches everything but ascii whitespace",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space does not match",
+                "data": " ",
+                "valid": false
+            },
+            {
+                "description": "latin-1 non-breaking-space matches (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/optional/format.json b/JSON-Schema-Test-Suite/tests/draft6/optional/format.json
new file mode 100644
index 0000000..b20a5e8
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/optional/format.json
@@ -0,0 +1,496 @@
+[
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "a valid date-time string",
+                "data": "1963-06-19T08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string without second fraction",
+                "data": "1963-06-19T08:30:06Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with plus offset",
+                "data": "1937-01-01T12:00:27.87+00:20",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with minus offset",
+                "data": "1990-12-31T15:59:50.123-08:00",
+                "valid": true
+            },
+            {
+                "description": "a invalid day in date-time string",
+                "data": "1990-02-31T15:59:60.123-08:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid offset in date-time string",
+                "data": "1990-12-31T15:59:60-24:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid closing Z after time-zone offset",
+                "data": "1963-06-19T08:30:06.28123+01:00Z",
+                "valid": false
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963 08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "case-insensitive T and Z",
+                "data": "1963-06-19t08:30:06.283185z",
+                "valid": true
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350T01:01:01",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "a valid URL with anchor tag",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with anchor tag and parantheses",
+                "data": "http://foo.com/blah_(wikipedia)_blah#cite-1",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with URL-encoded stuff",
+                "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff",
+                "valid": true
+            },
+            {
+                "description": "a valid puny-coded URL ",
+                "data": "http://xn--nw2a.xn--j6w193g/",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with many special characters",
+                "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid URL based on IPv4",
+                "data": "http://223.255.255.254",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with ftp scheme",
+                "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL for a simple text file",
+                "data": "http://www.ietf.org/rfc/rfc2396.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL ",
+                "data": "ldap://[2001:db8::7]/c=GB?objectClass?one",
+                "valid": true
+            },
+            {
+                "description": "a valid mailto URI",
+                "data": "mailto:John.Doe@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid newsgroup URI",
+                "data": "news:comp.infosystems.www.servers.unix",
+                "valid": true
+            },
+            {
+                "description": "a valid tel URI",
+                "data": "tel:+1-816-555-1212",
+                "valid": true
+            },
+            {
+                "description": "a valid URN",
+                "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
+                "valid": true
+            },
+            {
+                "description": "an invalid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": false
+            },
+            {
+                "description": "an invalid relative URI Reference",
+                "data": "/abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI though valid URI reference",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces",
+                "data": "http:// shouldfail.com",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces and missing scheme",
+                "data": ":// should fail",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of URI References",
+        "schema": {"format": "uri-reference"},
+        "tests": [
+            {
+                "description": "a valid URI",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid relative URI Reference",
+                "data": "/abc",
+                "valid": true
+            },
+            {
+                "description": "an invalid URI Reference",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "a valid URI Reference",
+                "data": "abc",
+                "valid": true
+            },
+            {
+                "description": "a valid URI fragment",
+                "data": "#fragment",
+                "valid": true
+            },
+            {
+                "description": "an invalid URI fragment",
+                "data": "#frag\\ment",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "format: uri-template",
+        "schema": {"format": "uri-template"},
+        "tests": [
+            {
+                "description": "a valid uri-template",
+                "data": "http://example.com/dictionary/{term:1}/{term}",
+                "valid": true
+            },
+            {
+                "description": "an invalid uri-template",
+                "data": "http://example.com/dictionary/{term:1}/{term",
+                "valid": false
+            },
+            {
+                "description": "a valid uri-template without variables",
+                "data": "http://example.com/dictionary",
+                "valid": true
+            },
+            {
+                "description": "a valid relative uri-template",
+                "data": "dictionary/{term:1}/{term}",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "a valid e-mail address",
+                "data": "joe.bloggs@example.com",
+                "valid": true
+            },
+            {
+                "description": "an invalid e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "a valid IP address",
+                "data": "192.168.0.1",
+                "valid": true
+            },
+            {
+                "description": "an IP address with too many components",
+                "data": "127.0.0.0.1",
+                "valid": false
+            },
+            {
+                "description": "an IP address with out-of-range values",
+                "data": "256.256.256.256",
+                "valid": false
+            },
+            {
+                "description": "an IP address without 4 components",
+                "data": "127.0",
+                "valid": false
+            },
+            {
+                "description": "an IP address as an integer",
+                "data": "0x7f000001",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "a valid IPv6 address",
+                "data": "::1",
+                "valid": true
+            },
+            {
+                "description": "an IPv6 address with out-of-range values",
+                "data": "12345::",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address with too many components",
+                "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address containing illegal characters",
+                "data": "::laptop",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validation of host names",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "a valid host name",
+                "data": "www.example.com",
+                "valid": true
+            },
+            {
+                "description": "a host name starting with an illegal character",
+                "data": "-a-host-name-that-starts-with--",
+                "valid": false
+            },
+            {
+                "description": "a host name containing illegal characters",
+                "data": "not_a_valid_host_name",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+                "valid": false
+            },
+            {
+                "description": "a host name starting with a digit",
+                "data": "1drv.ms",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of JSON-pointers (JSON String Representation)",
+        "schema": {"format": "json-pointer"},
+        "tests": [
+            {
+                "description": "a valid JSON-pointer",
+                "data": "/foo/bar~0/baz~1/%a",
+                "valid": true
+            },
+            {
+                "description": "not a valid JSON-pointer (~ not escaped)",
+                "data": "/foo/bar~",
+                "valid": false
+            },
+            {
+                "description": "valid JSON-pointer with empty segment",
+                "data": "/foo//bar",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer with the last empty segment",
+                "data": "/foo/bar/",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #1",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #2",
+                "data": "/foo",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #3",
+                "data": "/foo/0",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #4",
+                "data": "/",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #5",
+                "data": "/a~1b",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #6",
+                "data": "/c%d",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #7",
+                "data": "/e^f",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #8",
+                "data": "/g|h",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #9",
+                "data": "/i\\j",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #10",
+                "data": "/k\"l",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #11",
+                "data": "/ ",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #12",
+                "data": "/m~0n",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer used adding to the last array position",
+                "data": "/foo/-",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (- used as object member name)",
+                "data": "/foo/-/bar",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (multiple escaped characters)",
+                "data": "/~1~0~0~1~1",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (escaped with fraction part) #1",
+                "data": "/~1.1",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (escaped with fraction part) #2",
+                "data": "/~0.1",
+                "valid": true
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #1",
+                "data": "#",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #2",
+                "data": "#/",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #3",
+                "data": "#a",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (some escaped, but not all) #1",
+                "data": "/~0~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (some escaped, but not all) #2",
+                "data": "/~0/~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (wrong escape character) #1",
+                "data": "/~2",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (wrong escape character) #2",
+                "data": "/~-1",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (multiple characters not escaped)",
+                "data": "/~~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3",
+                "data": "a/a",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/optional/zeroTerminatedFloats.json b/JSON-Schema-Test-Suite/tests/draft6/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..1bcdf96
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+    {
+        "description": "some languages do not distinguish between different types of numeric value",
+        "schema": {
+            "type": "integer"
+        },
+        "tests": [
+            {
+                "description": "a float without fractional part is an integer",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/pattern.json b/JSON-Schema-Test-Suite/tests/draft6/pattern.json
new file mode 100644
index 0000000..25e7299
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/pattern.json
@@ -0,0 +1,34 @@
+[
+    {
+        "description": "pattern validation",
+        "schema": {"pattern": "^a*$"},
+        "tests": [
+            {
+                "description": "a matching pattern is valid",
+                "data": "aaa",
+                "valid": true
+            },
+            {
+                "description": "a non-matching pattern is invalid",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": true,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "pattern is not anchored",
+        "schema": {"pattern": "a+"},
+        "tests": [
+            {
+                "description": "matches a substring",
+                "data": "xxaayy",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/patternProperties.json b/JSON-Schema-Test-Suite/tests/draft6/patternProperties.json
new file mode 100644
index 0000000..1d04a16
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/patternProperties.json
@@ -0,0 +1,151 @@
+[
+    {
+        "description":
+            "patternProperties validates properties matching a regex",
+        "schema": {
+            "patternProperties": {
+                "f.*o": {"type": "integer"}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "multiple valid matches is valid",
+                "data": {"foo": 1, "foooooo" : 2},
+                "valid": true
+            },
+            {
+                "description": "a single invalid match is invalid",
+                "data": {"foo": "bar", "fooooo": 2},
+                "valid": false
+            },
+            {
+                "description": "multiple invalid matches is invalid",
+                "data": {"foo": "bar", "foooooo" : "baz"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple simultaneous patternProperties are validated",
+        "schema": {
+            "patternProperties": {
+                "a*": {"type": "integer"},
+                "aaa*": {"maximum": 20}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"a": 21},
+                "valid": true
+            },
+            {
+                "description": "a simultaneous match is valid",
+                "data": {"aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "multiple matches is valid",
+                "data": {"a": 21, "aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "an invalid due to one is invalid",
+                "data": {"a": "bar"},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to the other is invalid",
+                "data": {"aaaa": 31},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to both is invalid",
+                "data": {"aaa": "foo", "aaaa": 31},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "regexes are not anchored by default and are case sensitive",
+        "schema": {
+            "patternProperties": {
+                "[0-9]{2,}": { "type": "boolean" },
+                "X_": { "type": "string" }
+            }
+        },
+        "tests": [
+            {
+                "description": "non recognized members are ignored",
+                "data": { "answer 1": "42" },
+                "valid": true
+            },
+            {
+                "description": "recognized members are accounted for",
+                "data": { "a31b": null },
+                "valid": false
+            },
+            {
+                "description": "regexes are case sensitive",
+                "data": { "a_x_3": 3 },
+                "valid": true
+            },
+            {
+                "description": "regexes are case sensitive, 2",
+                "data": { "a_X_3": 3 },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "patternProperties with boolean schemas",
+        "schema": {
+            "patternProperties": {
+                "f.*": true,
+                "b.*": false
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property matching schema true is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "object with property matching schema false is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "object with both properties is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/properties.json b/JSON-Schema-Test-Suite/tests/draft6/properties.json
new file mode 100644
index 0000000..b86c181
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/properties.json
@@ -0,0 +1,167 @@
+[
+    {
+        "description": "object properties validation",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "both properties present and valid is valid",
+                "data": {"foo": 1, "bar": "baz"},
+                "valid": true
+            },
+            {
+                "description": "one property invalid is invalid",
+                "data": {"foo": 1, "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "both properties invalid is invalid",
+                "data": {"foo": [], "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "doesn't invalidate other properties",
+                "data": {"quux": []},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description":
+            "properties, patternProperties, additionalProperties interaction",
+        "schema": {
+            "properties": {
+                "foo": {"type": "array", "maxItems": 3},
+                "bar": {"type": "array"}
+            },
+            "patternProperties": {"f.o": {"minItems": 2}},
+            "additionalProperties": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "property validates property",
+                "data": {"foo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "property invalidates property",
+                "data": {"foo": [1, 2, 3, 4]},
+                "valid": false
+            },
+            {
+                "description": "patternProperty invalidates property",
+                "data": {"foo": []},
+                "valid": false
+            },
+            {
+                "description": "patternProperty validates nonproperty",
+                "data": {"fxo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "patternProperty invalidates nonproperty",
+                "data": {"fxo": []},
+                "valid": false
+            },
+            {
+                "description": "additionalProperty ignores property",
+                "data": {"bar": []},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty validates others",
+                "data": {"quux": 3},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty invalidates others",
+                "data": {"quux": "foo"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with boolean schema",
+        "schema": {
+            "properties": {
+                "foo": true,
+                "bar": false
+            }
+        },
+        "tests": [
+            {
+                "description": "no property present is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "only 'true' property present is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "only 'false' property present is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "both properties present is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with escaped characters",
+        "schema": {
+            "properties": {
+                "foo\nbar": {"type": "number"},
+                "foo\"bar": {"type": "number"},
+                "foo\\bar": {"type": "number"},
+                "foo\rbar": {"type": "number"},
+                "foo\tbar": {"type": "number"},
+                "foo\fbar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with all numbers is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1",
+                    "foo\\bar": "1",
+                    "foo\rbar": "1",
+                    "foo\tbar": "1",
+                    "foo\fbar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/propertyNames.json b/JSON-Schema-Test-Suite/tests/draft6/propertyNames.json
new file mode 100644
index 0000000..8423690
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/propertyNames.json
@@ -0,0 +1,78 @@
+[
+    {
+        "description": "propertyNames validation",
+        "schema": {
+            "propertyNames": {"maxLength": 3}
+        },
+        "tests": [
+            {
+                "description": "all property names valid",
+                "data": {
+                    "f": {},
+                    "foo": {}
+                },
+                "valid": true
+            },
+            {
+                "description": "some property names invalid",
+                "data": {
+                    "foo": {},
+                    "foobar": {}
+                },
+                "valid": false
+            },
+            {
+                "description": "object without properties is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3, 4],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "propertyNames with boolean schema true",
+        "schema": {"propertyNames": true},
+        "tests": [
+            {
+                "description": "object with any properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "propertyNames with boolean schema false",
+        "schema": {"propertyNames": false},
+        "tests": [
+            {
+                "description": "object with any properties is invalid",
+                "data": {"foo": 1},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/ref.json b/JSON-Schema-Test-Suite/tests/draft6/ref.json
new file mode 100644
index 0000000..53f3a9e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/ref.json
@@ -0,0 +1,443 @@
+[
+    {
+        "description": "root pointer ref",
+        "schema": {
+            "properties": {
+                "foo": {"$ref": "#"}
+            },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"foo": false},
+                "valid": true
+            },
+            {
+                "description": "recursive match",
+                "data": {"foo": {"foo": false}},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": false},
+                "valid": false
+            },
+            {
+                "description": "recursive mismatch",
+                "data": {"foo": {"bar": false}},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to object",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"$ref": "#/properties/foo"}
+            }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"bar": 3},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": true},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to array",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"$ref": "#/items/0"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "match array",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "mismatch array",
+                "data": [1, "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "escaped pointer ref",
+        "schema": {
+            "tilda~field": {"type": "integer"},
+            "slash/field": {"type": "integer"},
+            "percent%field": {"type": "integer"},
+            "properties": {
+                "tilda": {"$ref": "#/tilda~0field"},
+                "slash": {"$ref": "#/slash~1field"},
+                "percent": {"$ref": "#/percent%25field"}
+            }
+        },
+        "tests": [
+            {
+                "description": "slash invalid",
+                "data": {"slash": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "tilda invalid",
+                "data": {"tilda": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "percent invalid",
+                "data": {"percent": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "slash valid",
+                "data": {"slash": 123},
+                "valid": true
+            },
+            {
+                "description": "tilda valid",
+                "data": {"tilda": 123},
+                "valid": true
+            },
+            {
+                "description": "percent valid",
+                "data": {"percent": 123},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested refs",
+        "schema": {
+            "definitions": {
+                "a": {"type": "integer"},
+                "b": {"$ref": "#/definitions/a"},
+                "c": {"$ref": "#/definitions/b"}
+            },
+            "$ref": "#/definitions/c"
+        },
+        "tests": [
+            {
+                "description": "nested ref valid",
+                "data": 5,
+                "valid": true
+            },
+            {
+                "description": "nested ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref overrides any sibling keywords",
+        "schema": {
+            "definitions": {
+                "reffed": {
+                    "type": "array"
+                }
+            },
+            "properties": {
+                "foo": {
+                    "$ref": "#/definitions/reffed",
+                    "maxItems": 2
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "ref valid",
+                "data": { "foo": [] },
+                "valid": true
+            },
+            {
+                "description": "ref valid, maxItems ignored",
+                "data": { "foo": [ 1, 2, 3] },
+                "valid": true
+            },
+            {
+                "description": "ref invalid",
+                "data": { "foo": "string" },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "remote ref, containing refs itself",
+        "schema": {"$ref": "http://json-schema.org/draft-06/schema#"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": {"minLength": 1},
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": {"minLength": -1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "property named $ref that is not a reference",
+        "schema": {
+            "properties": {
+                "$ref": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "property named $ref valid",
+                "data": {"$ref": "a"},
+                "valid": true
+            },
+            {
+                "description": "property named $ref invalid",
+                "data": {"$ref": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "$ref to boolean schema true",
+        "schema": {
+            "$ref": "#/definitions/bool",
+            "definitions": {
+                "bool": true
+            }
+        },
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "$ref to boolean schema false",
+        "schema": {
+            "$ref": "#/definitions/bool",
+            "definitions": {
+                "bool": false
+            }
+        },
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Recursive references between schemas",
+        "schema": {
+            "$id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+                "meta": {"type": "string"},
+                "nodes": {
+                    "type": "array",
+                    "items": {"$ref": "node"}
+                }
+            },
+            "required": ["meta", "nodes"],
+            "definitions": {
+                "node": {
+                    "$id": "http://localhost:1234/node",
+                    "description": "node",
+                    "type": "object",
+                    "properties": {
+                        "value": {"type": "number"},
+                        "subtree": {"$ref": "tree"}
+                    },
+                    "required": ["value"]
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 1.1},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": "string is invalid"},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "refs with quote",
+        "schema": {
+            "properties": {
+                "foo\"bar": {"$ref": "#/definitions/foo%22bar"}
+            },
+            "definitions": {
+                "foo\"bar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with numbers is valid",
+                "data": {
+                    "foo\"bar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier",
+        "schema": {
+            "allOf": [{
+                "$ref": "#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "$id": "#foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with absolute URI",
+        "schema": {
+            "allOf": [{
+                "$ref": "http://localhost:1234/bar#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "$id": "http://localhost:1234/bar#foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with base URI change in subschema",
+        "schema": {
+            "$id": "http://localhost:1234/root",
+            "allOf": [{
+                "$ref": "http://localhost:1234/nested.json#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "$id": "nested.json",
+                    "definitions": {
+                        "B": {
+                            "$id": "#foo",
+                            "type": "integer"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/refRemote.json b/JSON-Schema-Test-Suite/tests/draft6/refRemote.json
new file mode 100644
index 0000000..819d326
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/refRemote.json
@@ -0,0 +1,171 @@
+[
+    {
+        "description": "remote ref",
+        "schema": {"$ref": "http://localhost:1234/integer.json"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "fragment within remote ref",
+        "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},
+        "tests": [
+            {
+                "description": "remote fragment valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote fragment invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref within remote ref",
+        "schema": {
+            "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"
+        },
+        "tests": [
+            {
+                "description": "ref within ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "ref within ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change",
+        "schema": {
+            "$id": "http://localhost:1234/",
+            "items": {
+                "$id": "folder/",
+                "items": {"$ref": "folderInteger.json"}
+            }
+        },
+        "tests": [
+            {
+                "description": "base URI change ref valid",
+                "data": [[1]],
+                "valid": true
+            },
+            {
+                "description": "base URI change ref invalid",
+                "data": [["a"]],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder",
+        "schema": {
+            "$id": "http://localhost:1234/scope_change_defs1.json",
+            "type" : "object",
+            "properties": {
+                "list": {"$ref": "#/definitions/baz"}
+            },
+            "definitions": {
+                "baz": {
+                    "$id": "folder/",
+                    "type": "array",
+                    "items": {"$ref": "folderInteger.json"}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder in subschema",
+        "schema": {
+            "$id": "http://localhost:1234/scope_change_defs2.json",
+            "type" : "object",
+            "properties": {
+                "list": {"$ref": "#/definitions/baz/definitions/bar"}
+            },
+            "definitions": {
+                "baz": {
+                    "$id": "folder/",
+                    "definitions": {
+                        "bar": {
+                            "type": "array",
+                            "items": {"$ref": "folderInteger.json"}
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "root ref in remote ref",
+        "schema": {
+            "$id": "http://localhost:1234/object",
+            "type": "object",
+            "properties": {
+                "name": {"$ref": "name.json#/definitions/orNull"}
+            }
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": {
+                    "name": "foo"
+                },
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": {
+                    "name": null
+                },
+                "valid": true
+            },
+            {
+                "description": "object is invalid",
+                "data": {
+                    "name": {
+                        "name": null
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/required.json b/JSON-Schema-Test-Suite/tests/draft6/required.json
new file mode 100644
index 0000000..abf18f3
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/required.json
@@ -0,0 +1,105 @@
+[
+    {
+        "description": "required validation",
+        "schema": {
+            "properties": {
+                "foo": {},
+                "bar": {}
+            },
+            "required": ["foo"]
+        },
+        "tests": [
+            {
+                "description": "present required property is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "non-present required property is invalid",
+                "data": {"bar": 1},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required default validation",
+        "schema": {
+            "properties": {
+                "foo": {}
+            }
+        },
+        "tests": [
+            {
+                "description": "not required by default",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with empty array",
+        "schema": {
+            "properties": {
+                "foo": {}
+            },
+            "required": []
+        },
+        "tests": [
+            {
+                "description": "property not required",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with escaped characters",
+        "schema": {
+            "required": [
+                "foo\nbar",
+                "foo\"bar",
+                "foo\\bar",
+                "foo\rbar",
+                "foo\tbar",
+                "foo\fbar"
+            ]
+        },
+        "tests": [
+            {
+                "description": "object with all properties present is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with some properties missing is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/type.json b/JSON-Schema-Test-Suite/tests/draft6/type.json
new file mode 100644
index 0000000..ea33b18
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/type.json
@@ -0,0 +1,464 @@
+[
+    {
+        "description": "integer type matches integers",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "an integer is an integer",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is not an integer",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an integer",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not an integer, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not an integer",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not an integer",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an integer",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an integer",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "number type matches numbers",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "an integer is a number",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is a number",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "a string is not a number",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not a number, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not a number",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a number",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a number",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a number",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "string type matches strings",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "1 is not a string",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not a string",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is a string",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a string is still a string, even if it looks like a number",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "an empty string is still a string",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "an object is not a string",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a string",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a string",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a string",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "object type matches objects",
+        "schema": {"type": "object"},
+        "tests": [
+            {
+                "description": "an integer is not an object",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an object",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an object",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is an object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "an array is not an object",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an object",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an object",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "array type matches arrays",
+        "schema": {"type": "array"},
+        "tests": [
+            {
+                "description": "an integer is not an array",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an array",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an array",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not an array",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is an array",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "a boolean is not an array",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an array",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "boolean type matches booleans",
+        "schema": {"type": "boolean"},
+        "tests": [
+            {
+                "description": "an integer is not a boolean",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "zero is not a boolean",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a float is not a boolean",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not a boolean",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not a boolean",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not a boolean",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a boolean",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is a boolean",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "false is a boolean",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is not a boolean",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "null type matches only the null object",
+        "schema": {"type": "null"},
+        "tests": [
+            {
+                "description": "an integer is not null",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not null",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "zero is not null",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a string is not null",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not null",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not null",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not null",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is not null",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "false is not null",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple types can be specified in an array",
+        "schema": {"type": ["integer", "string"]},
+        "tests": [
+            {
+                "description": "an integer is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a float is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "an object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type as array with one item",
+        "schema": {
+            "type": ["string"]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array or object",
+        "schema": {
+            "type": ["array", "object"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array, object or null",
+        "schema": {
+            "type": ["array", "object", "null"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft6/uniqueItems.json b/JSON-Schema-Test-Suite/tests/draft6/uniqueItems.json
new file mode 100644
index 0000000..d312ad7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft6/uniqueItems.json
@@ -0,0 +1,173 @@
+[
+    {
+        "description": "uniqueItems validation",
+        "schema": {"uniqueItems": true},
+        "tests": [
+            {
+                "description": "unique array of integers is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of integers is invalid",
+                "data": [1, 1],
+                "valid": false
+            },
+            {
+                "description": "numbers are unique if mathematically unequal",
+                "data": [1.0, 1.00, 1],
+                "valid": false
+            },
+            {
+                "description": "false is not equal to zero",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "true is not equal to one",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "unique array of objects is valid",
+                "data": [{"foo": "bar"}, {"foo": "baz"}],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of objects is invalid",
+                "data": [{"foo": "bar"}, {"foo": "bar"}],
+                "valid": false
+            },
+            {
+                "description": "unique array of nested objects is valid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : false}}}
+                ],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of nested objects is invalid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : true}}}
+                ],
+                "valid": false
+            },
+            {
+                "description": "unique array of arrays is valid",
+                "data": [["foo"], ["bar"]],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of arrays is invalid",
+                "data": [["foo"], ["foo"]],
+                "valid": false
+            },
+            {
+                "description": "1 and true are unique",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "0 and false are unique",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "unique heterogeneous types are valid",
+                "data": [{}, [1], true, null, 1],
+                "valid": true
+            },
+            {
+                "description": "non-unique heterogeneous types are invalid",
+                "data": [{}, [1], true, null, {}, 1],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "unique array extended from [false, true] is valid",
+                "data": [false, true, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "unique array extended from [true, false] is valid",
+                "data": [true, false, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "non-unique array extended from [false, true] is not valid",
+                "data": [false, true, "foo", "foo"],
+                "valid": false
+            },
+            {
+                "description": "non-unique array extended from [true, false] is not valid",
+                "data": [true, false, "foo", "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items and additionalItems=false",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}], 
+            "uniqueItems": true, 
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "extra items are invalid even if unique",
+                "data": [false, true, null],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json b/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json
new file mode 100644
index 0000000..abecc57
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json
@@ -0,0 +1,87 @@
+[
+    {
+        "description": "additionalItems as schema",
+        "schema": {
+            "items": [{}],
+            "additionalItems": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "additional items match schema",
+                "data": [ null, 2, 3, 4 ],
+                "valid": true
+            },
+            {
+                "description": "additional items do not match schema",
+                "data": [ null, 2, 3, "foo" ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "items is schema, no additionalItems",
+        "schema": {
+            "items": {},
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "all items match schema",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "array of items with no additionalItems",
+        "schema": {
+            "items": [{}, {}, {}],
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "fewer number of items present",
+                "data": [ 1, 2 ],
+                "valid": true
+            },
+            {
+                "description": "equal number of items present",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "additional items are not permitted",
+                "data": [ 1, 2, 3, 4 ],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalItems as false without items",
+        "schema": {"additionalItems": false},
+        "tests": [
+            {
+                "description":
+                    "items defaults to empty schema so everything is valid",
+                "data": [ 1, 2, 3, 4, 5 ],
+                "valid": true
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalItems are allowed by default",
+        "schema": {"items": [{"type": "integer"}]},
+        "tests": [
+            {
+                "description": "only the first item is validated",
+                "data": [1, "foo", false],
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json b/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json
new file mode 100644
index 0000000..ffeac6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json
@@ -0,0 +1,133 @@
+[
+    {
+        "description":
+            "additionalProperties being false does not allow other properties",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "patternProperties": { "^v": {} },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobarbaz",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "patternProperties are not additional properties",
+                "data": {"foo":1, "vroom": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "non-ASCII pattern with additionalProperties",
+        "schema": {
+            "patternProperties": {"^á": {}},
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "matching the pattern is valid",
+                "data": {"ármányos": 2},
+                "valid": true
+            },
+            {
+                "description": "not matching the pattern is invalid",
+                "data": {"élmény": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties allows a schema which should validate",
+        "schema": {
+            "properties": {"foo": {}, "bar": {}},
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "no additional properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1, "bar" : 2, "quux" : 12},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description":
+            "additionalProperties can exist by itself",
+        "schema": {
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "an additional valid property is valid",
+                "data": {"foo" : true},
+                "valid": true
+            },
+            {
+                "description": "an additional invalid property is invalid",
+                "data": {"foo" : 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties are allowed by default",
+        "schema": {"properties": {"foo": {}, "bar": {}}},
+        "tests": [
+            {
+                "description": "additional properties are allowed",
+                "data": {"foo": 1, "bar": 2, "quux": true},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "additionalProperties should not look in applicators",
+        "schema": {
+            "allOf": [
+                {"properties": {"foo": {}}}
+            ],
+            "additionalProperties": {"type": "boolean"}
+        },
+        "tests": [
+            {
+                "description": "properties defined in allOf are not allowed",
+                "data": {"foo": 1, "bar": true},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/allOf.json b/JSON-Schema-Test-Suite/tests/draft7/allOf.json
new file mode 100644
index 0000000..eb61209
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/allOf.json
@@ -0,0 +1,218 @@
+[
+    {
+        "description": "allOf",
+        "schema": {
+            "allOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "allOf",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "mismatch second",
+                "data": {"foo": "baz"},
+                "valid": false
+            },
+            {
+                "description": "mismatch first",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "baz", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with base schema",
+        "schema": {
+            "properties": {"bar": {"type": "integer"}},
+            "required": ["bar"],
+            "allOf" : [
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                },
+                {
+                    "properties": {
+                        "baz": {"type": "null"}
+                    },
+                    "required": ["baz"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": "quux", "bar": 2, "baz": null},
+                "valid": true
+            },
+            {
+                "description": "mismatch base schema",
+                "data": {"foo": "quux", "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch first allOf",
+                "data": {"bar": 2, "baz": null},
+                "valid": false
+            },
+            {
+                "description": "mismatch second allOf",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "mismatch both",
+                "data": {"bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf simple types",
+        "schema": {
+            "allOf": [
+                {"maximum": 30},
+                {"minimum": 20}
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": 25,
+                "valid": true
+            },
+            {
+                "description": "mismatch one",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, all true",
+        "schema": {"allOf": [true, true]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, some false",
+        "schema": {"allOf": [true, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with boolean schemas, all false",
+        "schema": {"allOf": [false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with one empty schema",
+        "schema": {
+            "allOf": [
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with two empty schemas",
+        "schema": {
+            "allOf": [
+                {},
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "any data is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "allOf with the first empty schema",
+        "schema": {
+            "allOf": [
+                {},
+                { "type": "number" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "allOf with the last empty schema",
+        "schema": {
+            "allOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/anyOf.json b/JSON-Schema-Test-Suite/tests/draft7/anyOf.json
new file mode 100644
index 0000000..ab5eb38
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/anyOf.json
@@ -0,0 +1,189 @@
+[
+    {
+        "description": "anyOf",
+        "schema": {
+            "anyOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid",
+                "data": 3,
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with base schema",
+        "schema": {
+            "type": "string",
+            "anyOf" : [
+                {
+                    "maxLength": 2
+                },
+                {
+                    "minLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one anyOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both anyOf invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, all true",
+        "schema": {"anyOf": [true, true]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, some true",
+        "schema": {"anyOf": [true, false]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "anyOf with boolean schemas, all false",
+        "schema": {"anyOf": [false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf complex types",
+        "schema": {
+            "anyOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first anyOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second anyOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both anyOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "neither anyOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "anyOf with one empty schema",
+        "schema": {
+            "anyOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is valid",
+                "data": 123,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested anyOf, to check validation semantics",
+        "schema": {
+            "anyOf": [
+                {
+                    "anyOf": [
+                        {
+                            "type": "null"
+                        }
+                    ]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "anything non-null is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json b/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json
new file mode 100644
index 0000000..6d40f23
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json
@@ -0,0 +1,104 @@
+[
+    {
+        "description": "boolean schema 'true'",
+        "schema": true,
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "boolean true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "boolean false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": "bar"},
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "array is valid",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "boolean schema 'false'",
+        "schema": false,
+        "tests": [
+            {
+                "description": "number is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "boolean true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "boolean false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "object is invalid",
+                "data": {"foo": "bar"},
+                "valid": false
+            },
+            {
+                "description": "empty object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "array is invalid",
+                "data": ["foo"],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/const.json b/JSON-Schema-Test-Suite/tests/draft7/const.json
new file mode 100644
index 0000000..c089625
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/const.json
@@ -0,0 +1,170 @@
+[
+    {
+        "description": "const validation",
+        "schema": {"const": 2},
+        "tests": [
+            {
+                "description": "same value is valid",
+                "data": 2,
+                "valid": true
+            },
+            {
+                "description": "another value is invalid",
+                "data": 5,
+                "valid": false
+            },
+            {
+                "description": "another type is invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with object",
+        "schema": {"const": {"foo": "bar", "baz": "bax"}},
+        "tests": [
+            {
+                "description": "same object is valid",
+                "data": {"foo": "bar", "baz": "bax"},
+                "valid": true
+            },
+            {
+                "description": "same object with different property order is valid",
+                "data": {"baz": "bax", "foo": "bar"},
+                "valid": true
+            },
+            {
+                "description": "another object is invalid",
+                "data": {"foo": "bar"},
+                "valid": false
+            },
+            {
+                "description": "another type is invalid",
+                "data": [1, 2],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with array",
+        "schema": {"const": [{ "foo": "bar" }]},
+        "tests": [
+            {
+                "description": "same array is valid",
+                "data": [{"foo": "bar"}],
+                "valid": true
+            },
+            {
+                "description": "another array item is invalid",
+                "data": [2],
+                "valid": false
+            },
+            {
+                "description": "array with additional items is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with null",
+        "schema": {"const": null},
+        "tests": [
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "not null is invalid",
+                "data": 0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with false does not match 0",
+        "schema": {"const": false},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with true does not match 1",
+        "schema": {"const": true},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "const with 0 does not match false",
+        "schema": {"const": 0},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "const with 1 does not match true",
+        "schema": {"const": 1},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/contains.json b/JSON-Schema-Test-Suite/tests/draft7/contains.json
new file mode 100644
index 0000000..67ecbd9
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/contains.json
@@ -0,0 +1,100 @@
+[
+    {
+        "description": "contains keyword validation",
+        "schema": {
+            "contains": {"minimum": 5}
+        },
+        "tests": [
+            {
+                "description": "array with item matching schema (5) is valid",
+                "data": [3, 4, 5],
+                "valid": true
+            },
+            {
+                "description": "array with item matching schema (6) is valid",
+                "data": [3, 4, 6],
+                "valid": true
+            },
+            {
+                "description": "array with two items matching schema (5, 6) is valid",
+                "data": [3, 4, 5, 6],
+                "valid": true
+            },
+            {
+                "description": "array without items matching schema is invalid",
+                "data": [2, 3, 4],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "not array is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with const keyword",
+        "schema": {
+            "contains": { "const": 5 }
+        },
+        "tests": [
+            {
+                "description": "array with item 5 is valid",
+                "data": [3, 4, 5],
+                "valid": true
+            },
+            {
+                "description": "array with two items 5 is valid",
+                "data": [3, 4, 5, 5],
+                "valid": true
+            },
+            {
+                "description": "array without item 5 is invalid",
+                "data": [1, 2, 3, 4],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with boolean schema true",
+        "schema": {"contains": true},
+        "tests": [
+            {
+                "description": "any non-empty array is valid",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "contains keyword with boolean schema false",
+        "schema": {"contains": false},
+        "tests": [
+            {
+                "description": "any non-empty array is invalid",
+                "data": ["foo"],
+                "valid": false
+            },
+            {
+                "description": "empty array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "non-arrays are valid",
+                "data": "contains does not apply to strings",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/default.json b/JSON-Schema-Test-Suite/tests/draft7/default.json
new file mode 100644
index 0000000..1762977
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/default.json
@@ -0,0 +1,49 @@
+[
+    {
+        "description": "invalid type for default",
+        "schema": {
+            "properties": {
+                "foo": {
+                    "type": "integer",
+                    "default": []
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"foo": 13},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid string value for default",
+        "schema": {
+            "properties": {
+                "bar": {
+                    "type": "string",
+                    "minLength": 4,
+                    "default": "bad"
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when property is specified",
+                "data": {"bar": "good"},
+                "valid": true
+            },
+            {
+                "description": "still valid when the invalid default is used",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/definitions.json b/JSON-Schema-Test-Suite/tests/draft7/definitions.json
new file mode 100644
index 0000000..4360406
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/definitions.json
@@ -0,0 +1,32 @@
+[
+    {
+        "description": "valid definition",
+        "schema": {"$ref": "http://json-schema.org/draft-07/schema#"},
+        "tests": [
+            {
+                "description": "valid definition schema",
+                "data": {
+                    "definitions": {
+                        "foo": {"type": "integer"}
+                    }
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "invalid definition",
+        "schema": {"$ref": "http://json-schema.org/draft-07/schema#"},
+        "tests": [
+            {
+                "description": "invalid definition schema",
+                "data": {
+                    "definitions": {
+                        "foo": {"type": 1}
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/dependencies.json b/JSON-Schema-Test-Suite/tests/draft7/dependencies.json
new file mode 100644
index 0000000..8dd78aa
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/dependencies.json
@@ -0,0 +1,268 @@
+[
+    {
+        "description": "dependencies",
+        "schema": {
+            "dependencies": {"bar": ["foo"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependant",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "with dependency",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["bar"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "dependencies with empty array",
+        "schema": {
+            "dependencies": {"bar": []}
+        },
+        "tests": [
+            {
+                "description": "empty object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "object with one property",
+                "data": {"bar": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies",
+        "schema": {
+            "dependencies": {"quux": ["foo", "bar"]}
+        },
+        "tests": [
+            {
+                "description": "neither",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "nondependants",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "with dependencies",
+                "data": {"foo": 1, "bar": 2, "quux": 3},
+                "valid": true
+            },
+            {
+                "description": "missing dependency",
+                "data": {"foo": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing other dependency",
+                "data": {"bar": 1, "quux": 2},
+                "valid": false
+            },
+            {
+                "description": "missing both dependencies",
+                "data": {"quux": 1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "multiple dependencies subschema",
+        "schema": {
+            "dependencies": {
+                "bar": {
+                    "properties": {
+                        "foo": {"type": "integer"},
+                        "bar": {"type": "integer"}
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "no dependency",
+                "data": {"foo": "quux"},
+                "valid": true
+            },
+            {
+                "description": "wrong type",
+                "data": {"foo": "quux", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "wrong type other",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            },
+            {
+                "description": "wrong type both",
+                "data": {"foo": "quux", "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "dependencies with boolean subschemas",
+        "schema": {
+            "dependencies": {
+                "foo": true,
+                "bar": false
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property having schema true is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "object with property having schema false is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "object with both properties is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "empty array of dependencies",
+        "schema": {
+            "dependencies": {
+                "foo": []
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property is valid",
+                "data": { "foo": 1 },
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "non-object is valid",
+                "data": 1,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "dependencies with escaped characters",
+        "schema": {
+            "dependencies": {
+                "foo\nbar": ["foo\rbar"],
+                "foo\tbar": {
+                    "minProperties": 4
+                },
+                "foo'bar": {"required": ["foo\"bar"]},
+                "foo\"bar": ["foo'bar"]
+            }
+        },
+        "tests": [
+            {
+                "description": "valid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\rbar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2,
+                    "b": 3,
+                    "c": 4
+                },
+                "valid": true
+            },
+            {
+                "description": "valid object 3",
+                "data": {
+                    "foo'bar": 1,
+                    "foo\"bar": 2
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid object 1",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 2",
+                "data": {
+                    "foo\tbar": 1,
+                    "a": 2
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 3",
+                "data": {
+                    "foo'bar": 1
+                },
+                "valid": false
+            },
+            {
+                "description": "invalid object 4",
+                "data": {
+                    "foo\"bar": 2
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/enum.json b/JSON-Schema-Test-Suite/tests/draft7/enum.json
new file mode 100644
index 0000000..32d7902
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/enum.json
@@ -0,0 +1,179 @@
+[
+    {
+        "description": "simple enum validation",
+        "schema": {"enum": [1, 2, 3]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": 4,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "heterogeneous enum validation",
+        "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
+        "tests": [
+            {
+                "description": "one of the enum is valid",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "something else is invalid",
+                "data": null,
+                "valid": false
+            },
+            {
+                "description": "objects are deep compared",
+                "data": {"foo": false},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enums in properties",
+        "schema": {
+            "type":"object",
+            "properties": {
+                "foo": {"enum":["foo"]},
+                "bar": {"enum":["bar"]}
+            },
+            "required": ["bar"]
+        },
+        "tests": [
+            {
+                "description": "both properties are valid",
+                "data": {"foo":"foo", "bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing optional property is valid",
+                "data": {"bar":"bar"},
+                "valid": true
+            },
+            {
+                "description": "missing required property is invalid",
+                "data": {"foo":"foo"},
+                "valid": false
+            },
+            {
+                "description": "missing all properties is invalid",
+                "data": {},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with escaped characters",
+        "schema": {
+            "enum": ["foo\nbar", "foo\rbar"]
+        },
+        "tests": [
+            {
+                "description": "member 1 is valid",
+                "data": "foo\nbar",
+                "valid": true
+            },
+            {
+                "description": "member 2 is valid",
+                "data": "foo\rbar",
+                "valid": true
+            },
+            {
+                "description": "another string is invalid",
+                "data": "abc",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with false does not match 0",
+        "schema": {"enum": [false]},
+        "tests": [
+            {
+                "description": "false is valid",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "integer zero is invalid",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "float zero is invalid",
+                "data": 0.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with true does not match 1",
+        "schema": {"enum": [true]},
+        "tests": [
+            {
+                "description": "true is valid",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "integer one is invalid",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "float one is invalid",
+                "data": 1.0,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "enum with 0 does not match false",
+        "schema": {"enum": [0]},
+        "tests": [
+            {
+                "description": "false is invalid",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "integer zero is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "float zero is valid",
+                "data": 0.0,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "enum with 1 does not match true",
+        "schema": {"enum": [1]},
+        "tests": [
+            {
+                "description": "true is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "integer one is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "float one is valid",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json b/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json
new file mode 100644
index 0000000..dc3cd70
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json
@@ -0,0 +1,30 @@
+[
+    {
+        "description": "exclusiveMaximum validation",
+        "schema": {
+            "exclusiveMaximum": 3.0
+        },
+        "tests": [
+            {
+                "description": "below the exclusiveMaximum is valid",
+                "data": 2.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 3.0,
+                "valid": false
+            },
+            {
+                "description": "above the exclusiveMaximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json b/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json
new file mode 100644
index 0000000..b38d7ec
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json
@@ -0,0 +1,30 @@
+[
+    {
+        "description": "exclusiveMinimum validation",
+        "schema": {
+            "exclusiveMinimum": 1.1
+        },
+        "tests": [
+            {
+                "description": "above the exclusiveMinimum is valid",
+                "data": 1.2,
+                "valid": true
+            },
+            {
+                "description": "boundary point is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "below the exclusiveMinimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/format.json b/JSON-Schema-Test-Suite/tests/draft7/format.json
new file mode 100644
index 0000000..93305f5
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/format.json
@@ -0,0 +1,614 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IDN e-mail addresses",
+        "schema": {"format": "idn-email"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of regexes",
+        "schema": {"format": "regex"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IDN hostnames",
+        "schema": {"format": "idn-hostname"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of hostnames",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date strings",
+        "schema": {"format": "date"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of time strings",
+        "schema": {"format": "time"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of JSON pointers",
+        "schema": {"format": "json-pointer"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of relative JSON pointers",
+        "schema": {"format": "relative-json-pointer"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IRIs",
+        "schema": {"format": "iri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of IRI references",
+        "schema": {"format": "iri-reference"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URI references",
+        "schema": {"format": "uri-reference"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of URI templates",
+        "schema": {"format": "uri-template"},
+        "tests": [
+            {
+                "description": "ignores integers",
+                "data": 12,
+                "valid": true
+            },
+            {
+                "description": "ignores floats",
+                "data": 13.7,
+                "valid": true
+            },
+            {
+                "description": "ignores objects",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores booleans",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "ignores null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json b/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json
new file mode 100644
index 0000000..be73281
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json
@@ -0,0 +1,188 @@
+[
+    {
+        "description": "ignore if without then or else",
+        "schema": {
+            "if": {
+                "const": 0
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when valid against lone if",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "valid when invalid against lone if",
+                "data": "hello",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ignore then without if",
+        "schema": {
+            "then": {
+                "const": 0
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when valid against lone then",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "valid when invalid against lone then",
+                "data": "hello",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ignore else without if",
+        "schema": {
+            "else": {
+                "const": 0
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when valid against lone else",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "valid when invalid against lone else",
+                "data": "hello",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "if and then without else",
+        "schema": {
+            "if": {
+                "exclusiveMaximum": 0
+            },
+            "then": {
+                "minimum": -10
+            }
+        },
+        "tests": [
+            {
+                "description": "valid through then",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "invalid through then",
+                "data": -100,
+                "valid": false
+            },
+            {
+                "description": "valid when if test fails",
+                "data": 3,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "if and else without then",
+        "schema": {
+            "if": {
+                "exclusiveMaximum": 0
+            },
+            "else": {
+                "multipleOf": 2
+            }
+        },
+        "tests": [
+            {
+                "description": "valid when if test passes",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "valid through else",
+                "data": 4,
+                "valid": true
+            },
+            {
+                "description": "invalid through else",
+                "data": 3,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "validate against correct branch, then vs else",
+        "schema": {
+            "if": {
+                "exclusiveMaximum": 0
+            },
+            "then": {
+                "minimum": -10
+            },
+            "else": {
+                "multipleOf": 2
+            }
+        },
+        "tests": [
+            {
+                "description": "valid through then",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "invalid through then",
+                "data": -100,
+                "valid": false
+            },
+            {
+                "description": "valid through else",
+                "data": 4,
+                "valid": true
+            },
+            {
+                "description": "invalid through else",
+                "data": 3,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "non-interference across combined schemas",
+        "schema": {
+            "allOf": [
+                {
+                    "if": {
+                        "exclusiveMaximum": 0
+                    }
+                },
+                {
+                    "then": {
+                        "minimum": -10
+                    }
+                },
+                {
+                    "else": {
+                        "multipleOf": 2
+                    }
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid, but would have been invalid through then",
+                "data": -100,
+                "valid": true
+            },
+            {
+                "description": "valid, but would have been invalid through else",
+                "data": 3,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/items.json b/JSON-Schema-Test-Suite/tests/draft7/items.json
new file mode 100644
index 0000000..67f1184
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/items.json
@@ -0,0 +1,250 @@
+[
+    {
+        "description": "a schema given for items",
+        "schema": {
+            "items": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [ 1, 2, 3 ],
+                "valid": true
+            },
+            {
+                "description": "wrong type of items",
+                "data": [1, "x"],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": {"foo" : "bar"},
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "length": 1
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "an array of schemas for items",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"type": "string"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "correct types",
+                "data": [ 1, "foo" ],
+                "valid": true
+            },
+            {
+                "description": "wrong types",
+                "data": [ "foo", 1 ],
+                "valid": false
+            },
+            {
+                "description": "incomplete array of items",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with additional items",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array",
+                "data": [ ],
+                "valid": true
+            },
+            {
+                "description": "JavaScript pseudo-array is valid",
+                "data": {
+                    "0": "invalid",
+                    "1": "valid",
+                    "length": 2
+                },
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schema (true)",
+        "schema": {"items": true},
+        "tests": [
+            {
+                "description": "any array is valid",
+                "data": [ 1, "foo", true ],
+                "valid": true
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schema (false)",
+        "schema": {"items": false},
+        "tests": [
+            {
+                "description": "any non-empty array is invalid",
+                "data": [ 1, "foo", true ],
+                "valid": false
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items with boolean schemas",
+        "schema": {
+            "items": [true, false]
+        },
+        "tests": [
+            {
+                "description": "array with one item is valid",
+                "data": [ 1 ],
+                "valid": true
+            },
+            {
+                "description": "array with two items is invalid",
+                "data": [ 1, "foo" ],
+                "valid": false
+            },
+            {
+                "description": "empty array is valid",
+                "data": [],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "items and subitems",
+        "schema": {
+            "definitions": {
+                "item": {
+                    "type": "array",
+                    "additionalItems": false,
+                    "items": [
+                        { "$ref": "#/definitions/sub-item" },
+                        { "$ref": "#/definitions/sub-item" }
+                    ]
+                },
+                "sub-item": {
+                    "type": "object",
+                    "required": ["foo"]
+                }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+                { "$ref": "#/definitions/item" },
+                { "$ref": "#/definitions/item" },
+                { "$ref": "#/definitions/item" }
+            ]
+        },
+        "tests": [
+            {
+                "description": "valid items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": true
+            },
+            {
+                "description": "too many items",
+                "data": [
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "too many sub-items",
+                "data": [
+                    [ {"foo": null}, {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong item",
+                "data": [
+                    {"foo": null},
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "wrong sub-item",
+                "data": [
+                    [ {}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ],
+                    [ {"foo": null}, {"foo": null} ]
+                ],
+                "valid": false
+            },
+            {
+                "description": "fewer items is valid",
+                "data": [
+                    [ {"foo": null} ],
+                    [ {"foo": null} ]
+                ],
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested items",
+        "schema": {
+            "type": "array",
+            "items": {
+                "type": "array",
+                "items": {
+                    "type": "array",
+                    "items": {
+                        "type": "array",
+                        "items": {
+                            "type": "number"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid nested array",
+                "data": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": true
+            },
+            {
+                "description": "nested array with invalid type",
+                "data": [[[["1"]], [[2],[3]]], [[[4], [5], [6]]]],
+                "valid": false
+            },
+            {
+                "description": "not deep enough",
+                "data": [[[1], [2],[3]], [[4], [5], [6]]],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/maxItems.json b/JSON-Schema-Test-Suite/tests/draft7/maxItems.json
new file mode 100644
index 0000000..3b53a6b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/maxItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maxItems validation",
+        "schema": {"maxItems": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": [1, 2, 3],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "foobar",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/maxLength.json b/JSON-Schema-Test-Suite/tests/draft7/maxLength.json
new file mode 100644
index 0000000..811d35b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/maxLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "maxLength validation",
+        "schema": {"maxLength": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": "f",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            },
+            {
+                "description": "two supplementary Unicode code points is long enough",
+                "data": "\uD83D\uDCA9\uD83D\uDCA9",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json b/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json
new file mode 100644
index 0000000..513731e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "maxProperties validation",
+        "schema": {"maxProperties": 2},
+        "tests": [
+            {
+                "description": "shorter is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "too long is invalid",
+                "data": {"foo": 1, "bar": 2, "baz": 3},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/maximum.json b/JSON-Schema-Test-Suite/tests/draft7/maximum.json
new file mode 100644
index 0000000..8150984
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/maximum.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "maximum validation",
+        "schema": {"maximum": 3.0},
+        "tests": [
+            {
+                "description": "below the maximum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 3.0,
+                "valid": true
+            },
+            {
+                "description": "above the maximum is invalid",
+                "data": 3.5,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/minItems.json b/JSON-Schema-Test-Suite/tests/draft7/minItems.json
new file mode 100644
index 0000000..ed51188
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/minItems.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "minItems validation",
+        "schema": {"minItems": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": [1],
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "ignores non-arrays",
+                "data": "",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/minLength.json b/JSON-Schema-Test-Suite/tests/draft7/minLength.json
new file mode 100644
index 0000000..3f09158
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/minLength.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "minLength validation",
+        "schema": {"minLength": 2},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": "fo",
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": "f",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "one supplementary Unicode code point is not long enough",
+                "data": "\uD83D\uDCA9",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/minProperties.json b/JSON-Schema-Test-Suite/tests/draft7/minProperties.json
new file mode 100644
index 0000000..49a0726
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/minProperties.json
@@ -0,0 +1,38 @@
+[
+    {
+        "description": "minProperties validation",
+        "schema": {"minProperties": 1},
+        "tests": [
+            {
+                "description": "longer is valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "exact length is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "too short is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/minimum.json b/JSON-Schema-Test-Suite/tests/draft7/minimum.json
new file mode 100644
index 0000000..2a9c42b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/minimum.json
@@ -0,0 +1,59 @@
+[
+    {
+        "description": "minimum validation",
+        "schema": {"minimum": 1.1},
+        "tests": [
+            {
+                "description": "above the minimum is valid",
+                "data": 2.6,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": 0.6,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "minimum validation with signed integer",
+        "schema": {"minimum": -2},
+        "tests": [
+            {
+                "description": "negative above the minimum is valid",
+                "data": -1,
+                "valid": true
+            },
+            {
+                "description": "positive above the minimum is valid",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "boundary point is valid",
+                "data": -2,
+                "valid": true
+            },
+            {
+                "description": "below the minimum is invalid",
+                "data": -3,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "x",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json b/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json
new file mode 100644
index 0000000..ca3b761
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json
@@ -0,0 +1,60 @@
+[
+    {
+        "description": "by int",
+        "schema": {"multipleOf": 2},
+        "tests": [
+            {
+                "description": "int by int",
+                "data": 10,
+                "valid": true
+            },
+            {
+                "description": "int by int fail",
+                "data": 7,
+                "valid": false
+            },
+            {
+                "description": "ignores non-numbers",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "by number",
+        "schema": {"multipleOf": 1.5},
+        "tests": [
+            {
+                "description": "zero is multiple of anything",
+                "data": 0,
+                "valid": true
+            },
+            {
+                "description": "4.5 is multiple of 1.5",
+                "data": 4.5,
+                "valid": true
+            },
+            {
+                "description": "35 is not multiple of 1.5",
+                "data": 35,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "by small number",
+        "schema": {"multipleOf": 0.0001},
+        "tests": [
+            {
+                "description": "0.0075 is multiple of 0.0001",
+                "data": 0.0075,
+                "valid": true
+            },
+            {
+                "description": "0.00751 is not multiple of 0.0001",
+                "data": 0.00751,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/not.json b/JSON-Schema-Test-Suite/tests/draft7/not.json
new file mode 100644
index 0000000..98de0ed
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/not.json
@@ -0,0 +1,117 @@
+[
+    {
+        "description": "not",
+        "schema": {
+            "not": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "allowed",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "disallowed",
+                "data": 1,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not multiple types",
+        "schema": {
+            "not": {"type": ["integer", "boolean"]}
+        },
+        "tests": [
+            {
+                "description": "valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "other mismatch",
+                "data": true,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not more complex schema",
+        "schema": {
+            "not": {
+                "type": "object",
+                "properties": {
+                    "foo": {
+                        "type": "string"
+                    }
+                }
+             }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "other match",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"foo": "bar"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "forbidden property",
+        "schema": {
+            "properties": {
+                "foo": { 
+                    "not": {}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "property present",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "property absent",
+                "data": {"bar": 1, "baz": 2},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "not with boolean schema true",
+        "schema": {"not": true},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "not with boolean schema false",
+        "schema": {"not": false},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/oneOf.json b/JSON-Schema-Test-Suite/tests/draft7/oneOf.json
new file mode 100644
index 0000000..57640b7
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/oneOf.json
@@ -0,0 +1,206 @@
+[
+    {
+        "description": "oneOf",
+        "schema": {
+            "oneOf": [
+                {
+                    "type": "integer"
+                },
+                {
+                    "minimum": 2
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid",
+                "data": 2.5,
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid",
+                "data": 1.5,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with base schema",
+        "schema": {
+            "type": "string",
+            "oneOf" : [
+                {
+                    "minLength": 2
+                },
+                {
+                    "maxLength": 4
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "mismatch base schema",
+                "data": 3,
+                "valid": false
+            },
+            {
+                "description": "one oneOf valid",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, all true",
+        "schema": {"oneOf": [true, true, true]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, one true",
+        "schema": {"oneOf": [true, false, false]},
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, more than one true",
+        "schema": {"oneOf": [true, true, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with boolean schemas, all false",
+        "schema": {"oneOf": [false, false, false]},
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf complex types",
+        "schema": {
+            "oneOf": [
+                {
+                    "properties": {
+                        "bar": {"type": "integer"}
+                    },
+                    "required": ["bar"]
+                },
+                {
+                    "properties": {
+                        "foo": {"type": "string"}
+                    },
+                    "required": ["foo"]
+                }
+            ]
+        },
+        "tests": [
+            {
+                "description": "first oneOf valid (complex)",
+                "data": {"bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second oneOf valid (complex)",
+                "data": {"foo": "baz"},
+                "valid": true
+            },
+            {
+                "description": "both oneOf valid (complex)",
+                "data": {"foo": "baz", "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "neither oneOf valid (complex)",
+                "data": {"foo": 2, "bar": "quux"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with empty schema",
+        "schema": {
+            "oneOf": [
+                { "type": "number" },
+                {}
+            ]
+        },
+        "tests": [
+            {
+                "description": "one valid - valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "oneOf with required",
+        "schema": {
+            "type": "object",
+            "oneOf": [
+                { "required": ["foo", "bar"] },
+                { "required": ["foo", "baz"] }
+            ]
+        },
+        "tests": [
+            {
+                "description": "both invalid - invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "first valid - valid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": true
+            },
+            {
+                "description": "second valid - valid",
+                "data": {"foo": 1, "baz": 3},
+                "valid": true
+            },
+            {
+                "description": "both valid - invalid",
+                "data": {"foo": 1, "bar": 2, "baz" : 3},
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json b/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json
new file mode 100644
index 0000000..fac275e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json
@@ -0,0 +1,105 @@
+[
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a bignum is an integer",
+                "data": 12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a bignum is a number",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "integer",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "a negative bignum is an integer",
+                "data": -12345678910111213141516171819202122232425262728293031,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "number",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "a negative bignum is a number",
+                "data": -98249283749234923498293171823948729348710298301928331,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "string",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "a bignum is not a string",
+                "data": 98249283749234923498293171823948729348710298301928331,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"maximum": 18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision",
+        "schema": {
+            "exclusiveMaximum": 972783798187987123879878123.18878137
+        },
+        "tests": [
+            {
+                "description": "comparison works for high numbers",
+                "data": 972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "integer comparison",
+        "schema": {"minimum": -18446744073709551615},
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -18446744073709551600,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "float comparison with high precision on negative numbers",
+        "schema": {
+            "exclusiveMinimum": -972783798187987123879878123.18878137
+        },
+        "tests": [
+            {
+                "description": "comparison works for very negative numbers",
+                "data": -972783798187987123879878123.188781371,
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/content.json b/JSON-Schema-Test-Suite/tests/draft7/optional/content.json
new file mode 100644
index 0000000..3f5a743
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/content.json
@@ -0,0 +1,77 @@
+[
+    {
+        "description": "validation of string-encoded content based on media type",
+        "schema": {
+            "contentMediaType": "application/json"
+        },
+        "tests": [
+            {
+                "description": "a valid JSON document",
+                "data": "{\"foo\": \"bar\"}",
+                "valid": true
+            },
+            {
+                "description": "an invalid JSON document",
+                "data": "{:}",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of binary string-encoding",
+        "schema": {
+            "contentEncoding": "base64"
+        },
+        "tests": [
+            {
+                "description": "a valid base64 string",
+                "data": "eyJmb28iOiAiYmFyIn0K",
+                "valid": true
+            },
+            {
+                "description": "an invalid base64 string (% is not a valid character)",
+                "data": "eyJmb28iOi%iYmFyIn0K",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "validation of binary-encoded media type documents",
+        "schema": {
+            "contentMediaType": "application/json",
+            "contentEncoding": "base64"
+        },
+        "tests": [
+            {
+                "description": "a valid base64-encoded JSON document",
+                "data": "eyJmb28iOiAiYmFyIn0K",
+                "valid": true
+            },
+            {
+                "description": "a validly-encoded invalid JSON document",
+                "data": "ezp9Cg==",
+                "valid": false
+            },
+            {
+                "description": "an invalid base64 string that is valid JSON",
+                "data": "{}",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": 100,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json b/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json
new file mode 100644
index 0000000..d82e0fe
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json
@@ -0,0 +1,213 @@
+[
+    {
+        "description": "ECMA 262 regex non-compliance",
+        "schema": { "format": "regex" },
+        "tests": [
+            {
+                "description": "ECMA 262 has no support for \\Z anchor from .NET",
+                "data": "^\\S(|(.|\\n)*\\S)\\Z",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex $ does not match trailing newline",
+        "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+        },
+        "tests": [
+            {
+                "description": "matches in Python, but should not in jsonschema",
+                "data": "abc\n",
+                "valid": false
+            },
+            {
+                "description": "should match",
+                "data": "abc",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex converts \\a to ascii BEL",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\a",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0007",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and upper letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cC",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 regex escapes control codes with \\c and lower letter",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+        },
+        "tests": [
+            {
+                "description": "does not match",
+                "data": "\\cc",
+                "valid": false
+            },
+            {
+                "description": "matches",
+                "data": "\u0003",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\d matches ascii digits only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero matches",
+                "data": "0",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO does not match (unlike e.g. Python)",
+                "data": "߀",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) does not match",
+                "data": "\u07c0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\D matches everything but ascii digits",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+        },
+        "tests": [
+            {
+                "description": "ASCII zero does not match",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "NKO DIGIT ZERO matches (unlike e.g. Python)",
+                "data": "߀",
+                "valid": true
+            },
+            {
+                "description": "NKO DIGIT ZERO (as \\u escape) matches",
+                "data": "\u07c0",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches ascii letters only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' matches",
+                "data": "a",
+                "valid": true
+            },
+            {
+                "description": "latin-1 e-acute does not match (unlike e.g. Python)",
+                "data": "é",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\w matches everything but ascii letters",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+        },
+        "tests": [
+            {
+                "description": "ASCII 'a' does not match",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "latin-1 e-acute matches (unlike e.g. Python)",
+                "data": "é",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\s matches ascii whitespace only",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space matches",
+                "data": " ",
+                "valid": true
+            },
+            {
+                "description": "latin-1 non-breaking-space does not match (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ECMA 262 \\S matches everything but ascii whitespace",
+        "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+        },
+        "tests": [
+            {
+                "description": "ASCII space does not match",
+                "data": " ",
+                "valid": false
+            },
+            {
+                "description": "latin-1 non-breaking-space matches (unlike e.g. Python)",
+                "data": "\u00a0",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json
new file mode 100644
index 0000000..dfccee6
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json
@@ -0,0 +1,53 @@
+[
+    {
+        "description": "validation of date-time strings",
+        "schema": {"format": "date-time"},
+        "tests": [
+            {
+                "description": "a valid date-time string",
+                "data": "1963-06-19T08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string without second fraction",
+                "data": "1963-06-19T08:30:06Z",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with plus offset",
+                "data": "1937-01-01T12:00:27.87+00:20",
+                "valid": true
+            },
+            {
+                "description": "a valid date-time string with minus offset",
+                "data": "1990-12-31T15:59:50.123-08:00",
+                "valid": true
+            },
+            {
+                "description": "a invalid day in date-time string",
+                "data": "1990-02-31T15:59:60.123-08:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid offset in date-time string",
+                "data": "1990-12-31T15:59:60-24:00",
+                "valid": false
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963 08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "case-insensitive T and Z",
+                "data": "1963-06-19t08:30:06.283185z",
+                "valid": true
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350T01:01:01",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json
new file mode 100644
index 0000000..cd23baa
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json
@@ -0,0 +1,23 @@
+[
+    {
+        "description": "validation of date strings",
+        "schema": {"format": "date"},
+        "tests": [
+            {
+                "description": "a valid date string",
+                "data": "1963-06-19",
+                "valid": true
+            },
+            {
+                "description": "an invalid date-time string",
+                "data": "06/19/1963",
+                "valid": false
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "2013-350",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json
new file mode 100644
index 0000000..c837c84
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "validation of e-mail addresses",
+        "schema": {"format": "email"},
+        "tests": [
+            {
+                "description": "a valid e-mail address",
+                "data": "joe.bloggs@example.com",
+                "valid": true
+            },
+            {
+                "description": "an invalid e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json
new file mode 100644
index 0000000..1da83a4
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json
@@ -0,0 +1,39 @@
+[
+    {
+        "description": "validation of host names",
+        "schema": {"format": "hostname"},
+        "tests": [
+            {
+                "description": "a valid host name",
+                "data": "www.example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid punycoded IDN hostname",
+                "data": "xn--4gbwdl.xn--wgbh1c",
+                "valid": true
+            },
+            {
+                "description": "a host name starting with an illegal character",
+                "data": "-a-host-name-that-starts-with--",
+                "valid": false
+            },
+            {
+                "description": "a host name containing illegal characters",
+                "data": "not_a_valid_host_name",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+                "valid": false
+            },
+
+            {
+                "description": "a host name starting with a digit",
+                "data": "1drv.ms",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json
new file mode 100644
index 0000000..637409e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "validation of an internationalized e-mail addresses",
+        "schema": {"format": "idn-email"},
+        "tests": [
+            {
+                "description": "a valid idn e-mail (example@example.test in Hangul)",
+                "data": "실례@실례.테스트",
+                "valid": true
+            },
+            {
+                "description": "an invalid idn e-mail address",
+                "data": "2962",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json
new file mode 100644
index 0000000..3291820
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "validation of internationalized host names",
+        "schema": {"format": "idn-hostname"},
+        "tests": [
+            {
+                "description": "a valid host name (example.test in Hangul)",
+                "data": "실례.테스트",
+                "valid": true
+            },
+            {
+                "description": "illegal first char U+302E Hangul single dot tone mark",
+                "data": "〮실례.테스트",
+                "valid": false
+            },
+            {
+                "description": "contains illegal char U+302E Hangul single dot tone mark",
+                "data": "실〮례.테스트",
+                "valid": false
+            },
+            {
+                "description": "a host name with a component too long",
+                "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json
new file mode 100644
index 0000000..661148a
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "validation of IP addresses",
+        "schema": {"format": "ipv4"},
+        "tests": [
+            {
+                "description": "a valid IP address",
+                "data": "192.168.0.1",
+                "valid": true
+            },
+            {
+                "description": "an IP address with too many components",
+                "data": "127.0.0.0.1",
+                "valid": false
+            },
+            {
+                "description": "an IP address with out-of-range values",
+                "data": "256.256.256.256",
+                "valid": false
+            },
+            {
+                "description": "an IP address without 4 components",
+                "data": "127.0",
+                "valid": false
+            },
+            {
+                "description": "an IP address as an integer",
+                "data": "0x7f000001",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json
new file mode 100644
index 0000000..f67559b
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "validation of IPv6 addresses",
+        "schema": {"format": "ipv6"},
+        "tests": [
+            {
+                "description": "a valid IPv6 address",
+                "data": "::1",
+                "valid": true
+            },
+            {
+                "description": "an IPv6 address with out-of-range values",
+                "data": "12345::",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address with too many components",
+                "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+                "valid": false
+            },
+            {
+                "description": "an IPv6 address containing illegal characters",
+                "data": "::laptop",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json
new file mode 100644
index 0000000..1fd779c
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json
@@ -0,0 +1,43 @@
+[
+    {
+        "description": "validation of IRI References",
+        "schema": {"format": "iri-reference"},
+        "tests": [
+            {
+                "description": "a valid IRI",
+                "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx",
+                "valid": true
+            },
+            {
+                "description": "a valid protocol-relative IRI Reference",
+                "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx",
+                "valid": true
+            },
+            {
+                "description": "a valid relative IRI Reference",
+                "data": "/âππ",
+                "valid": true
+            },
+            {
+                "description": "an invalid IRI Reference",
+                "data": "\\\\WINDOWS\\filëßåré",
+                "valid": false
+            },
+            {
+                "description": "a valid IRI Reference",
+                "data": "âππ",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI fragment",
+                "data": "#ƒrägmênt",
+                "valid": true
+            },
+            {
+                "description": "an invalid IRI fragment",
+                "data": "#ƒräg\\mênt",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json
new file mode 100644
index 0000000..ed54094
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json
@@ -0,0 +1,53 @@
+[
+    {
+        "description": "validation of IRIs",
+        "schema": {"format": "iri"},
+        "tests": [
+            {
+                "description": "a valid IRI with anchor tag",
+                "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI with anchor tag and parantheses",
+                "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI with URL-encoded stuff",
+                "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI with many special characters",
+                "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid IRI based on IPv6",
+                "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]",
+                "valid": true
+            },
+            {
+                "description": "an invalid IRI based on IPv6",
+                "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+                "valid": false
+            },
+            {
+                "description": "an invalid relative IRI Reference",
+                "data": "/abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid IRI",
+                "data": "\\\\WINDOWS\\filëßåré",
+                "valid": false
+            },
+            {
+                "description": "an invalid IRI though valid IRI reference",
+                "data": "âππ",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json
new file mode 100644
index 0000000..65c2f06
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json
@@ -0,0 +1,168 @@
+[
+    {
+        "description": "validation of JSON-pointers (JSON String Representation)",
+        "schema": {"format": "json-pointer"},
+        "tests": [
+            {
+                "description": "a valid JSON-pointer",
+                "data": "/foo/bar~0/baz~1/%a",
+                "valid": true
+            },
+            {
+                "description": "not a valid JSON-pointer (~ not escaped)",
+                "data": "/foo/bar~",
+                "valid": false
+            },
+            {
+                "description": "valid JSON-pointer with empty segment",
+                "data": "/foo//bar",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer with the last empty segment",
+                "data": "/foo/bar/",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #1",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #2",
+                "data": "/foo",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #3",
+                "data": "/foo/0",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #4",
+                "data": "/",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #5",
+                "data": "/a~1b",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #6",
+                "data": "/c%d",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #7",
+                "data": "/e^f",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #8",
+                "data": "/g|h",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #9",
+                "data": "/i\\j",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #10",
+                "data": "/k\"l",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #11",
+                "data": "/ ",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer as stated in RFC 6901 #12",
+                "data": "/m~0n",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer used adding to the last array position",
+                "data": "/foo/-",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (- used as object member name)",
+                "data": "/foo/-/bar",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (multiple escaped characters)",
+                "data": "/~1~0~0~1~1",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (escaped with fraction part) #1",
+                "data": "/~1.1",
+                "valid": true
+            },
+            {
+                "description": "valid JSON-pointer (escaped with fraction part) #2",
+                "data": "/~0.1",
+                "valid": true
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #1",
+                "data": "#",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #2",
+                "data": "#/",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (URI Fragment Identifier) #3",
+                "data": "#a",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (some escaped, but not all) #1",
+                "data": "/~0~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (some escaped, but not all) #2",
+                "data": "/~0/~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (wrong escape character) #1",
+                "data": "/~2",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (wrong escape character) #2",
+                "data": "/~-1",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (multiple characters not escaped)",
+                "data": "/~~",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1",
+                "data": "a",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2",
+                "data": "0",
+                "valid": false
+            },
+            {
+                "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3",
+                "data": "a/a",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json
new file mode 100644
index 0000000..d99d021
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json
@@ -0,0 +1,18 @@
+[
+    {
+        "description": "validation of regular expressions",
+        "schema": {"format": "regex"},
+        "tests": [
+            {
+                "description": "a valid regular expression",
+                "data": "([abc])+\\s+$",
+                "valid": true
+            },
+            {
+                "description": "a regular expression with unclosed parens is invalid",
+                "data": "^(abc]",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json
new file mode 100644
index 0000000..ceeb743
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json
@@ -0,0 +1,33 @@
+[
+    {
+        "description": "validation of Relative JSON Pointers (RJP)",
+        "schema": {"format": "relative-json-pointer"},
+        "tests": [
+            {
+                "description": "a valid upwards RJP",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "a valid downwards RJP",  
+                "data": "0/foo/bar",
+                "valid": true
+            },
+            {
+                "description": "a valid up and then down RJP, with array index",
+                "data": "2/0/baz/1/zip",
+                "valid": true
+            },
+            {
+                "description": "a valid RJP taking the member or index name",
+                "data": "0#",
+                "valid": true
+            },
+            {
+                "description": "an invalid RJP that is a valid JSON Pointer",
+                "data": "/foo/bar",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json
new file mode 100644
index 0000000..4ec8a01
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json
@@ -0,0 +1,23 @@
+[
+    {
+        "description": "validation of time strings",
+        "schema": {"format": "time"},
+        "tests": [
+            {
+                "description": "a valid time string",
+                "data": "08:30:06.283185Z",
+                "valid": true
+            },
+            {
+                "description": "an invalid time string",
+                "data": "08:30:06 PST",
+                "valid": false
+            },
+            {
+                "description": "only RFC3339 not all of ISO 8601 are valid",
+                "data": "01:01:01,1111",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json
new file mode 100644
index 0000000..e4c9eef
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json
@@ -0,0 +1,43 @@
+[
+    {
+        "description": "validation of URI References",
+        "schema": {"format": "uri-reference"},
+        "tests": [
+            {
+                "description": "a valid URI",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid relative URI Reference",
+                "data": "/abc",
+                "valid": true
+            },
+            {
+                "description": "an invalid URI Reference",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "a valid URI Reference",
+                "data": "abc",
+                "valid": true
+            },
+            {
+                "description": "a valid URI fragment",
+                "data": "#fragment",
+                "valid": true
+            },
+            {
+                "description": "an invalid URI fragment",
+                "data": "#frag\\ment",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json
new file mode 100644
index 0000000..33ab76e
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json
@@ -0,0 +1,28 @@
+[
+    {
+        "description": "format: uri-template",
+        "schema": {"format": "uri-template"},
+        "tests": [
+            {
+                "description": "a valid uri-template",
+                "data": "http://example.com/dictionary/{term:1}/{term}",
+                "valid": true
+            },
+            {
+                "description": "an invalid uri-template",
+                "data": "http://example.com/dictionary/{term:1}/{term",
+                "valid": false
+            },
+            {
+                "description": "a valid uri-template without variables",
+                "data": "http://example.com/dictionary",
+                "valid": true
+            },
+            {
+                "description": "a valid relative uri-template",
+                "data": "dictionary/{term:1}/{term}",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json b/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json
new file mode 100644
index 0000000..25cc40c
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json
@@ -0,0 +1,103 @@
+[
+    {
+        "description": "validation of URIs",
+        "schema": {"format": "uri"},
+        "tests": [
+            {
+                "description": "a valid URL with anchor tag",
+                "data": "http://foo.bar/?baz=qux#quux",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with anchor tag and parantheses",
+                "data": "http://foo.com/blah_(wikipedia)_blah#cite-1",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with URL-encoded stuff",
+                "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff",
+                "valid": true
+            },
+            {
+                "description": "a valid puny-coded URL ",
+                "data": "http://xn--nw2a.xn--j6w193g/",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with many special characters",
+                "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid URL based on IPv4",
+                "data": "http://223.255.255.254",
+                "valid": true
+            },
+            {
+                "description": "a valid URL with ftp scheme",
+                "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL for a simple text file",
+                "data": "http://www.ietf.org/rfc/rfc2396.txt",
+                "valid": true
+            },
+            {
+                "description": "a valid URL ",
+                "data": "ldap://[2001:db8::7]/c=GB?objectClass?one",
+                "valid": true
+            },
+            {
+                "description": "a valid mailto URI",
+                "data": "mailto:John.Doe@example.com",
+                "valid": true
+            },
+            {
+                "description": "a valid newsgroup URI",
+                "data": "news:comp.infosystems.www.servers.unix",
+                "valid": true
+            },
+            {
+                "description": "a valid tel URI",
+                "data": "tel:+1-816-555-1212",
+                "valid": true
+            },
+            {
+                "description": "a valid URN",
+                "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
+                "valid": true
+            },
+            {
+                "description": "an invalid protocol-relative URI Reference",
+                "data": "//foo.bar/?baz=qux#quux",
+                "valid": false
+            },
+            {
+                "description": "an invalid relative URI Reference",
+                "data": "/abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI",
+                "data": "\\\\WINDOWS\\fileshare",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI though valid URI reference",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces",
+                "data": "http:// shouldfail.com",
+                "valid": false
+            },
+            {
+                "description": "an invalid URI with spaces and missing scheme",
+                "data": ":// should fail",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/optional/zeroTerminatedFloats.json b/JSON-Schema-Test-Suite/tests/draft7/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..1bcdf96
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+    {
+        "description": "some languages do not distinguish between different types of numeric value",
+        "schema": {
+            "type": "integer"
+        },
+        "tests": [
+            {
+                "description": "a float without fractional part is an integer",
+                "data": 1.0,
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/pattern.json b/JSON-Schema-Test-Suite/tests/draft7/pattern.json
new file mode 100644
index 0000000..25e7299
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/pattern.json
@@ -0,0 +1,34 @@
+[
+    {
+        "description": "pattern validation",
+        "schema": {"pattern": "^a*$"},
+        "tests": [
+            {
+                "description": "a matching pattern is valid",
+                "data": "aaa",
+                "valid": true
+            },
+            {
+                "description": "a non-matching pattern is invalid",
+                "data": "abc",
+                "valid": false
+            },
+            {
+                "description": "ignores non-strings",
+                "data": true,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "pattern is not anchored",
+        "schema": {"pattern": "a+"},
+        "tests": [
+            {
+                "description": "matches a substring",
+                "data": "xxaayy",
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json b/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json
new file mode 100644
index 0000000..1d04a16
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json
@@ -0,0 +1,151 @@
+[
+    {
+        "description":
+            "patternProperties validates properties matching a regex",
+        "schema": {
+            "patternProperties": {
+                "f.*o": {"type": "integer"}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "multiple valid matches is valid",
+                "data": {"foo": 1, "foooooo" : 2},
+                "valid": true
+            },
+            {
+                "description": "a single invalid match is invalid",
+                "data": {"foo": "bar", "fooooo": 2},
+                "valid": false
+            },
+            {
+                "description": "multiple invalid matches is invalid",
+                "data": {"foo": "bar", "foooooo" : "baz"},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": ["foo"],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple simultaneous patternProperties are validated",
+        "schema": {
+            "patternProperties": {
+                "a*": {"type": "integer"},
+                "aaa*": {"maximum": 20}
+            }
+        },
+        "tests": [
+            {
+                "description": "a single valid match is valid",
+                "data": {"a": 21},
+                "valid": true
+            },
+            {
+                "description": "a simultaneous match is valid",
+                "data": {"aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "multiple matches is valid",
+                "data": {"a": 21, "aaaa": 18},
+                "valid": true
+            },
+            {
+                "description": "an invalid due to one is invalid",
+                "data": {"a": "bar"},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to the other is invalid",
+                "data": {"aaaa": 31},
+                "valid": false
+            },
+            {
+                "description": "an invalid due to both is invalid",
+                "data": {"aaa": "foo", "aaaa": 31},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "regexes are not anchored by default and are case sensitive",
+        "schema": {
+            "patternProperties": {
+                "[0-9]{2,}": { "type": "boolean" },
+                "X_": { "type": "string" }
+            }
+        },
+        "tests": [
+            {
+                "description": "non recognized members are ignored",
+                "data": { "answer 1": "42" },
+                "valid": true
+            },
+            {
+                "description": "recognized members are accounted for",
+                "data": { "a31b": null },
+                "valid": false
+            },
+            {
+                "description": "regexes are case sensitive",
+                "data": { "a_x_3": 3 },
+                "valid": true
+            },
+            {
+                "description": "regexes are case sensitive, 2",
+                "data": { "a_X_3": 3 },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "patternProperties with boolean schemas",
+        "schema": {
+            "patternProperties": {
+                "f.*": true,
+                "b.*": false
+            }
+        },
+        "tests": [
+            {
+                "description": "object with property matching schema true is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "object with property matching schema false is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "object with both properties is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/properties.json b/JSON-Schema-Test-Suite/tests/draft7/properties.json
new file mode 100644
index 0000000..b86c181
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/properties.json
@@ -0,0 +1,167 @@
+[
+    {
+        "description": "object properties validation",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "both properties present and valid is valid",
+                "data": {"foo": 1, "bar": "baz"},
+                "valid": true
+            },
+            {
+                "description": "one property invalid is invalid",
+                "data": {"foo": 1, "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "both properties invalid is invalid",
+                "data": {"foo": [], "bar": {}},
+                "valid": false
+            },
+            {
+                "description": "doesn't invalidate other properties",
+                "data": {"quux": []},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description":
+            "properties, patternProperties, additionalProperties interaction",
+        "schema": {
+            "properties": {
+                "foo": {"type": "array", "maxItems": 3},
+                "bar": {"type": "array"}
+            },
+            "patternProperties": {"f.o": {"minItems": 2}},
+            "additionalProperties": {"type": "integer"}
+        },
+        "tests": [
+            {
+                "description": "property validates property",
+                "data": {"foo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "property invalidates property",
+                "data": {"foo": [1, 2, 3, 4]},
+                "valid": false
+            },
+            {
+                "description": "patternProperty invalidates property",
+                "data": {"foo": []},
+                "valid": false
+            },
+            {
+                "description": "patternProperty validates nonproperty",
+                "data": {"fxo": [1, 2]},
+                "valid": true
+            },
+            {
+                "description": "patternProperty invalidates nonproperty",
+                "data": {"fxo": []},
+                "valid": false
+            },
+            {
+                "description": "additionalProperty ignores property",
+                "data": {"bar": []},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty validates others",
+                "data": {"quux": 3},
+                "valid": true
+            },
+            {
+                "description": "additionalProperty invalidates others",
+                "data": {"quux": "foo"},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with boolean schema",
+        "schema": {
+            "properties": {
+                "foo": true,
+                "bar": false
+            }
+        },
+        "tests": [
+            {
+                "description": "no property present is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "only 'true' property present is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "only 'false' property present is invalid",
+                "data": {"bar": 2},
+                "valid": false
+            },
+            {
+                "description": "both properties present is invalid",
+                "data": {"foo": 1, "bar": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "properties with escaped characters",
+        "schema": {
+            "properties": {
+                "foo\nbar": {"type": "number"},
+                "foo\"bar": {"type": "number"},
+                "foo\\bar": {"type": "number"},
+                "foo\rbar": {"type": "number"},
+                "foo\tbar": {"type": "number"},
+                "foo\fbar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with all numbers is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1",
+                    "foo\\bar": "1",
+                    "foo\rbar": "1",
+                    "foo\tbar": "1",
+                    "foo\fbar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json b/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json
new file mode 100644
index 0000000..8423690
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json
@@ -0,0 +1,78 @@
+[
+    {
+        "description": "propertyNames validation",
+        "schema": {
+            "propertyNames": {"maxLength": 3}
+        },
+        "tests": [
+            {
+                "description": "all property names valid",
+                "data": {
+                    "f": {},
+                    "foo": {}
+                },
+                "valid": true
+            },
+            {
+                "description": "some property names invalid",
+                "data": {
+                    "foo": {},
+                    "foobar": {}
+                },
+                "valid": false
+            },
+            {
+                "description": "object without properties is valid",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "ignores arrays",
+                "data": [1, 2, 3, 4],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "foobar",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "propertyNames with boolean schema true",
+        "schema": {"propertyNames": true},
+        "tests": [
+            {
+                "description": "object with any properties is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "propertyNames with boolean schema false",
+        "schema": {"propertyNames": false},
+        "tests": [
+            {
+                "description": "object with any properties is invalid",
+                "data": {"foo": 1},
+                "valid": false
+            },
+            {
+                "description": "empty object is valid",
+                "data": {},
+                "valid": true
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/ref.json b/JSON-Schema-Test-Suite/tests/draft7/ref.json
new file mode 100644
index 0000000..44b8ed2
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/ref.json
@@ -0,0 +1,443 @@
+[
+    {
+        "description": "root pointer ref",
+        "schema": {
+            "properties": {
+                "foo": {"$ref": "#"}
+            },
+            "additionalProperties": false
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"foo": false},
+                "valid": true
+            },
+            {
+                "description": "recursive match",
+                "data": {"foo": {"foo": false}},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": false},
+                "valid": false
+            },
+            {
+                "description": "recursive mismatch",
+                "data": {"foo": {"bar": false}},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to object",
+        "schema": {
+            "properties": {
+                "foo": {"type": "integer"},
+                "bar": {"$ref": "#/properties/foo"}
+            }
+        },
+        "tests": [
+            {
+                "description": "match",
+                "data": {"bar": 3},
+                "valid": true
+            },
+            {
+                "description": "mismatch",
+                "data": {"bar": true},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "relative pointer ref to array",
+        "schema": {
+            "items": [
+                {"type": "integer"},
+                {"$ref": "#/items/0"}
+            ]
+        },
+        "tests": [
+            {
+                "description": "match array",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "mismatch array",
+                "data": [1, "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "escaped pointer ref",
+        "schema": {
+            "tilda~field": {"type": "integer"},
+            "slash/field": {"type": "integer"},
+            "percent%field": {"type": "integer"},
+            "properties": {
+                "tilda": {"$ref": "#/tilda~0field"},
+                "slash": {"$ref": "#/slash~1field"},
+                "percent": {"$ref": "#/percent%25field"}
+            }
+        },
+        "tests": [
+            {
+                "description": "slash invalid",
+                "data": {"slash": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "tilda invalid",
+                "data": {"tilda": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "percent invalid",
+                "data": {"percent": "aoeu"},
+                "valid": false
+            },
+            {
+                "description": "slash valid",
+                "data": {"slash": 123},
+                "valid": true
+            },
+            {
+                "description": "tilda valid",
+                "data": {"tilda": 123},
+                "valid": true
+            },
+            {
+                "description": "percent valid",
+                "data": {"percent": 123},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "nested refs",
+        "schema": {
+            "definitions": {
+                "a": {"type": "integer"},
+                "b": {"$ref": "#/definitions/a"},
+                "c": {"$ref": "#/definitions/b"}
+            },
+            "$ref": "#/definitions/c"
+        },
+        "tests": [
+            {
+                "description": "nested ref valid",
+                "data": 5,
+                "valid": true
+            },
+            {
+                "description": "nested ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref overrides any sibling keywords",
+        "schema": {
+            "definitions": {
+                "reffed": {
+                    "type": "array"
+                }
+            },
+            "properties": {
+                "foo": {
+                    "$ref": "#/definitions/reffed",
+                    "maxItems": 2
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "ref valid",
+                "data": { "foo": [] },
+                "valid": true
+            },
+            {
+                "description": "ref valid, maxItems ignored",
+                "data": { "foo": [ 1, 2, 3] },
+                "valid": true
+            },
+            {
+                "description": "ref invalid",
+                "data": { "foo": "string" },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "remote ref, containing refs itself",
+        "schema": {"$ref": "http://json-schema.org/draft-07/schema#"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": {"minLength": 1},
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": {"minLength": -1},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "property named $ref that is not a reference",
+        "schema": {
+            "properties": {
+                "$ref": {"type": "string"}
+            }
+        },
+        "tests": [
+            {
+                "description": "property named $ref valid",
+                "data": {"$ref": "a"},
+                "valid": true
+            },
+            {
+                "description": "property named $ref invalid",
+                "data": {"$ref": 2},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "$ref to boolean schema true",
+        "schema": {
+            "$ref": "#/definitions/bool",
+            "definitions": {
+                "bool": true
+            }
+        },
+        "tests": [
+            {
+                "description": "any value is valid",
+                "data": "foo",
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "$ref to boolean schema false",
+        "schema": {
+            "$ref": "#/definitions/bool",
+            "definitions": {
+                "bool": false
+            }
+        },
+        "tests": [
+            {
+                "description": "any value is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Recursive references between schemas",
+        "schema": {
+            "$id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+                "meta": {"type": "string"},
+                "nodes": {
+                    "type": "array",
+                    "items": {"$ref": "node"}
+                }
+            },
+            "required": ["meta", "nodes"],
+            "definitions": {
+                "node": {
+                    "$id": "http://localhost:1234/node",
+                    "description": "node",
+                    "type": "object",
+                    "properties": {
+                        "value": {"type": "number"},
+                        "subtree": {"$ref": "tree"}
+                    },
+                    "required": ["value"]
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "valid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 1.1},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": true
+            },
+            {
+                "description": "invalid tree",
+                "data": { 
+                    "meta": "root",
+                    "nodes": [
+                        {
+                            "value": 1,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": "string is invalid"},
+                                    {"value": 1.2}
+                                ]
+                            }
+                        },
+                        {
+                            "value": 2,
+                            "subtree": {
+                                "meta": "child",
+                                "nodes": [
+                                    {"value": 2.1},
+                                    {"value": 2.2}
+                                ]
+                            }
+                        }
+                    ]
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "refs with quote",
+        "schema": {
+            "properties": {
+                "foo\"bar": {"$ref": "#/definitions/foo%22bar"}
+            },
+            "definitions": {
+                "foo\"bar": {"type": "number"}
+            }
+        },
+        "tests": [
+            {
+                "description": "object with numbers is valid",
+                "data": {
+                    "foo\"bar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with strings is invalid",
+                "data": {
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier",
+        "schema": {
+            "allOf": [{
+                "$ref": "#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "$id": "#foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with absolute URI",
+        "schema": {
+            "allOf": [{
+                "$ref": "http://localhost:1234/bar#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "$id": "http://localhost:1234/bar#foo",
+                    "type": "integer"
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "Location-independent identifier with base URI change in subschema",
+        "schema": {
+            "$id": "http://localhost:1234/root",
+            "allOf": [{
+                "$ref": "http://localhost:1234/nested.json#foo"
+            }],
+            "definitions": {
+                "A": {
+                    "$id": "nested.json",
+                    "definitions": {
+                        "B": {
+                            "$id": "#foo",
+                            "type": "integer"
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "data": 1,
+                "description": "match",
+                "valid": true
+            },
+            {
+                "data": "a",
+                "description": "mismatch",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/refRemote.json b/JSON-Schema-Test-Suite/tests/draft7/refRemote.json
new file mode 100644
index 0000000..819d326
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/refRemote.json
@@ -0,0 +1,171 @@
+[
+    {
+        "description": "remote ref",
+        "schema": {"$ref": "http://localhost:1234/integer.json"},
+        "tests": [
+            {
+                "description": "remote ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "fragment within remote ref",
+        "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},
+        "tests": [
+            {
+                "description": "remote fragment valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "remote fragment invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "ref within remote ref",
+        "schema": {
+            "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"
+        },
+        "tests": [
+            {
+                "description": "ref within ref valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "ref within ref invalid",
+                "data": "a",
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change",
+        "schema": {
+            "$id": "http://localhost:1234/",
+            "items": {
+                "$id": "folder/",
+                "items": {"$ref": "folderInteger.json"}
+            }
+        },
+        "tests": [
+            {
+                "description": "base URI change ref valid",
+                "data": [[1]],
+                "valid": true
+            },
+            {
+                "description": "base URI change ref invalid",
+                "data": [["a"]],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder",
+        "schema": {
+            "$id": "http://localhost:1234/scope_change_defs1.json",
+            "type" : "object",
+            "properties": {
+                "list": {"$ref": "#/definitions/baz"}
+            },
+            "definitions": {
+                "baz": {
+                    "$id": "folder/",
+                    "type": "array",
+                    "items": {"$ref": "folderInteger.json"}
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "base URI change - change folder in subschema",
+        "schema": {
+            "$id": "http://localhost:1234/scope_change_defs2.json",
+            "type" : "object",
+            "properties": {
+                "list": {"$ref": "#/definitions/baz/definitions/bar"}
+            },
+            "definitions": {
+                "baz": {
+                    "$id": "folder/",
+                    "definitions": {
+                        "bar": {
+                            "type": "array",
+                            "items": {"$ref": "folderInteger.json"}
+                        }
+                    }
+                }
+            }
+        },
+        "tests": [
+            {
+                "description": "number is valid",
+                "data": {"list": [1]},
+                "valid": true
+            },
+            {
+                "description": "string is invalid",
+                "data": {"list": ["a"]},
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "root ref in remote ref",
+        "schema": {
+            "$id": "http://localhost:1234/object",
+            "type": "object",
+            "properties": {
+                "name": {"$ref": "name.json#/definitions/orNull"}
+            }
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": {
+                    "name": "foo"
+                },
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": {
+                    "name": null
+                },
+                "valid": true
+            },
+            {
+                "description": "object is invalid",
+                "data": {
+                    "name": {
+                        "name": null
+                    }
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/required.json b/JSON-Schema-Test-Suite/tests/draft7/required.json
new file mode 100644
index 0000000..abf18f3
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/required.json
@@ -0,0 +1,105 @@
+[
+    {
+        "description": "required validation",
+        "schema": {
+            "properties": {
+                "foo": {},
+                "bar": {}
+            },
+            "required": ["foo"]
+        },
+        "tests": [
+            {
+                "description": "present required property is valid",
+                "data": {"foo": 1},
+                "valid": true
+            },
+            {
+                "description": "non-present required property is invalid",
+                "data": {"bar": 1},
+                "valid": false
+            },
+            {
+                "description": "ignores arrays",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "ignores strings",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "ignores other non-objects",
+                "data": 12,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required default validation",
+        "schema": {
+            "properties": {
+                "foo": {}
+            }
+        },
+        "tests": [
+            {
+                "description": "not required by default",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with empty array",
+        "schema": {
+            "properties": {
+                "foo": {}
+            },
+            "required": []
+        },
+        "tests": [
+            {
+                "description": "property not required",
+                "data": {},
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "required with escaped characters",
+        "schema": {
+            "required": [
+                "foo\nbar",
+                "foo\"bar",
+                "foo\\bar",
+                "foo\rbar",
+                "foo\tbar",
+                "foo\fbar"
+            ]
+        },
+        "tests": [
+            {
+                "description": "object with all properties present is valid",
+                "data": {
+                    "foo\nbar": 1,
+                    "foo\"bar": 1,
+                    "foo\\bar": 1,
+                    "foo\rbar": 1,
+                    "foo\tbar": 1,
+                    "foo\fbar": 1
+                },
+                "valid": true
+            },
+            {
+                "description": "object with some properties missing is invalid",
+                "data": {
+                    "foo\nbar": "1",
+                    "foo\"bar": "1"
+                },
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/type.json b/JSON-Schema-Test-Suite/tests/draft7/type.json
new file mode 100644
index 0000000..ea33b18
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/type.json
@@ -0,0 +1,464 @@
+[
+    {
+        "description": "integer type matches integers",
+        "schema": {"type": "integer"},
+        "tests": [
+            {
+                "description": "an integer is an integer",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is not an integer",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an integer",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not an integer, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not an integer",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not an integer",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an integer",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an integer",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "number type matches numbers",
+        "schema": {"type": "number"},
+        "tests": [
+            {
+                "description": "an integer is a number",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a float is a number",
+                "data": 1.1,
+                "valid": true
+            },
+            {
+                "description": "a string is not a number",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "a string is still not a number, even if it looks like one",
+                "data": "1",
+                "valid": false
+            },
+            {
+                "description": "an object is not a number",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a number",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a number",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a number",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "string type matches strings",
+        "schema": {"type": "string"},
+        "tests": [
+            {
+                "description": "1 is not a string",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not a string",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is a string",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a string is still a string, even if it looks like a number",
+                "data": "1",
+                "valid": true
+            },
+            {
+                "description": "an empty string is still a string",
+                "data": "",
+                "valid": true
+            },
+            {
+                "description": "an object is not a string",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a string",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not a string",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not a string",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "object type matches objects",
+        "schema": {"type": "object"},
+        "tests": [
+            {
+                "description": "an integer is not an object",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an object",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an object",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is an object",
+                "data": {},
+                "valid": true
+            },
+            {
+                "description": "an array is not an object",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is not an object",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an object",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "array type matches arrays",
+        "schema": {"type": "array"},
+        "tests": [
+            {
+                "description": "an integer is not an array",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not an array",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not an array",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an object is not an array",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is an array",
+                "data": [],
+                "valid": true
+            },
+            {
+                "description": "a boolean is not an array",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is not an array",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "boolean type matches booleans",
+        "schema": {"type": "boolean"},
+        "tests": [
+            {
+                "description": "an integer is not a boolean",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "zero is not a boolean",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a float is not a boolean",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "a string is not a boolean",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not a boolean",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not a boolean",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not a boolean",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is a boolean",
+                "data": true,
+                "valid": true
+            },
+            {
+                "description": "false is a boolean",
+                "data": false,
+                "valid": true
+            },
+            {
+                "description": "null is not a boolean",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "null type matches only the null object",
+        "schema": {"type": "null"},
+        "tests": [
+            {
+                "description": "an integer is not null",
+                "data": 1,
+                "valid": false
+            },
+            {
+                "description": "a float is not null",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "zero is not null",
+                "data": 0,
+                "valid": false
+            },
+            {
+                "description": "a string is not null",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "an empty string is not null",
+                "data": "",
+                "valid": false
+            },
+            {
+                "description": "an object is not null",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is not null",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "true is not null",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "false is not null",
+                "data": false,
+                "valid": false
+            },
+            {
+                "description": "null is null",
+                "data": null,
+                "valid": true
+            }
+        ]
+    },
+    {
+        "description": "multiple types can be specified in an array",
+        "schema": {"type": ["integer", "string"]},
+        "tests": [
+            {
+                "description": "an integer is valid",
+                "data": 1,
+                "valid": true
+            },
+            {
+                "description": "a string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "a float is invalid",
+                "data": 1.1,
+                "valid": false
+            },
+            {
+                "description": "an object is invalid",
+                "data": {},
+                "valid": false
+            },
+            {
+                "description": "an array is invalid",
+                "data": [],
+                "valid": false
+            },
+            {
+                "description": "a boolean is invalid",
+                "data": true,
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type as array with one item",
+        "schema": {
+            "type": ["string"]
+        },
+        "tests": [
+            {
+                "description": "string is valid",
+                "data": "foo",
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array or object",
+        "schema": {
+            "type": ["array", "object"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            },
+            {
+                "description": "null is invalid",
+                "data": null,
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "type: array, object or null",
+        "schema": {
+            "type": ["array", "object", "null"]
+        },
+        "tests": [
+            {
+                "description": "array is valid",
+                "data": [1,2,3],
+                "valid": true
+            },
+            {
+                "description": "object is valid",
+                "data": {"foo": 123},
+                "valid": true
+            },
+            {
+                "description": "null is valid",
+                "data": null,
+                "valid": true
+            },
+            {
+                "description": "number is invalid",
+                "data": 123,
+                "valid": false
+            },
+            {
+                "description": "string is invalid",
+                "data": "foo",
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json b/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json
new file mode 100644
index 0000000..d0a94d8
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json
@@ -0,0 +1,173 @@
+[
+    {
+        "description": "uniqueItems validation",
+        "schema": {"uniqueItems": true},
+        "tests": [
+            {
+                "description": "unique array of integers is valid",
+                "data": [1, 2],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of integers is invalid",
+                "data": [1, 1],
+                "valid": false
+            },
+            {
+                "description": "numbers are unique if mathematically unequal",
+                "data": [1.0, 1.00, 1],
+                "valid": false
+            },
+            {
+                "description": "false is not equal to zero",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "true is not equal to one",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "unique array of objects is valid",
+                "data": [{"foo": "bar"}, {"foo": "baz"}],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of objects is invalid",
+                "data": [{"foo": "bar"}, {"foo": "bar"}],
+                "valid": false
+            },
+            {
+                "description": "unique array of nested objects is valid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : false}}}
+                ],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of nested objects is invalid",
+                "data": [
+                    {"foo": {"bar" : {"baz" : true}}},
+                    {"foo": {"bar" : {"baz" : true}}}
+                ],
+                "valid": false
+            },
+            {
+                "description": "unique array of arrays is valid",
+                "data": [["foo"], ["bar"]],
+                "valid": true
+            },
+            {
+                "description": "non-unique array of arrays is invalid",
+                "data": [["foo"], ["foo"]],
+                "valid": false
+            },
+            {
+                "description": "1 and true are unique",
+                "data": [1, true],
+                "valid": true
+            },
+            {
+                "description": "0 and false are unique",
+                "data": [0, false],
+                "valid": true
+            },
+            {
+                "description": "unique heterogeneous types are valid",
+                "data": [{}, [1], true, null, 1],
+                "valid": true
+            },
+            {
+                "description": "non-unique heterogeneous types are invalid",
+                "data": [{}, [1], true, null, {}, 1],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}],
+            "uniqueItems": true
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "unique array extended from [false, true] is valid",
+                "data": [false, true, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "unique array extended from [true, false] is valid",
+                "data": [true, false, "foo", "bar"],
+                "valid": true
+            },
+            {
+                "description": "non-unique array extended from [false, true] is not valid",
+                "data": [false, true, "foo", "foo"],
+                "valid": false
+            },
+            {
+                "description": "non-unique array extended from [true, false] is not valid",
+                "data": [true, false, "foo", "foo"],
+                "valid": false
+            }
+        ]
+    },
+    {
+        "description": "uniqueItems with an array of items and additionalItems=false",
+        "schema": {
+            "items": [{"type": "boolean"}, {"type": "boolean"}],
+            "uniqueItems": true,
+            "additionalItems": false
+        },
+        "tests": [
+            {
+                "description": "[false, true] from items array is valid",
+                "data": [false, true],
+                "valid": true
+            },
+            {
+                "description": "[true, false] from items array is valid",
+                "data": [true, false],
+                "valid": true
+            },
+            {
+                "description": "[false, false] from items array is not valid",
+                "data": [false, false],
+                "valid": false
+            },
+            {
+                "description": "[true, true] from items array is not valid",
+                "data": [true, true],
+                "valid": false
+            },
+            {
+                "description": "extra items are invalid even if unique",
+                "data": [false, true, null],
+                "valid": false
+            }
+        ]
+    }
+]
diff --git a/JSON-Schema-Test-Suite/tests/latest b/JSON-Schema-Test-Suite/tests/latest
new file mode 120000
index 0000000..90f70db
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tests/latest
@@ -0,0 +1 @@
+draft2019-09
\ No newline at end of file
diff --git a/JSON-Schema-Test-Suite/tox.ini b/JSON-Schema-Test-Suite/tox.ini
new file mode 100644
index 0000000..9c4e949
--- /dev/null
+++ b/JSON-Schema-Test-Suite/tox.ini
@@ -0,0 +1,9 @@
+[tox]
+minversion = 1.6
+envlist = sanity
+skipsdist = True
+
+[testenv:sanity]
+# used just for validating the structure of the test case files themselves
+deps = jsonschema
+commands = {envpython} bin/jsonschema_suite check
diff --git a/README.md b/README.md
index fd53d6c..8891ef4 100644
--- a/README.md
+++ b/README.md
@@ -110,10 +110,41 @@ JSONSchemer.schema(
   # 'net/http'/proc/lambda/respond_to?(:call)
   # 'net/http': proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
   # default: proc { |uri| raise UnknownRef, uri.to_s }
-  ref_resolver: 'net/http'
+  ref_resolver: 'net/http',
+  
+  # use different method to match regexes
+  # 'ecma'/'ruby'/proc/lambda/respond_to?(:call)
+  # default: 'ecma'
+  regexp_resolver: proc do |pattern|
+    RE2::Regexp.new(pattern)
+  end
 )
 ```
 
+## CLI
+
+The `json_schemer` executable takes a JSON schema file as the first argument followed by one or more JSON data files to validate. If there are any validation errors, it outputs them and returns an error code.
+
+Validation errors are output as single-line JSON objects. The `--errors` option can be used to limit the number of errors returned or prevent output entirely (and fail fast).
+
+The schema or data can also be read from stdin using `-`.
+
+```
+% json_schemer --help
+Usage:
+  json_schemer [options] <schema> <data>...
+  json_schemer [options] <schema> -
+  json_schemer [options] - <data>...
+  json_schemer -h | --help
+  json_schemer --version
+
+Options:
+  -e, --errors MAX                 Maximum number of errors to output
+                                   Use "0" to validate with no output
+  -h, --help                       Show help
+  -v, --version                    Show version
+```
+
 ## Development
 
 After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 0000000..9275675
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'rake' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require "pathname"
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
+  Pathname.new(__FILE__).realpath)
+
+bundle_binstub = File.expand_path("../bundle", __FILE__)
+
+if File.file?(bundle_binstub)
+  if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
+    load(bundle_binstub)
+  else
+    abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
+Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
+  end
+end
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("rake", "rake")
diff --git a/debian/changelog b/debian/changelog
index 155b857..c497e29 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+ruby-json-schemer (0.2.24-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Wed, 11 Jan 2023 02:24:37 -0000
+
 ruby-json-schemer (0.2.18-2) unstable; urgency=medium
 
   * Reupload to unstable
diff --git a/exe/json_schemer b/exe/json_schemer
new file mode 100755
index 0000000..3f81b9e
--- /dev/null
+++ b/exe/json_schemer
@@ -0,0 +1,62 @@
+#!/usr/bin/env ruby
+
+require 'json'
+require 'optparse'
+require 'pathname'
+require 'json_schemer'
+
+parser = OptionParser.new('Usage:', 32, '  ')
+parser.separator("  #{parser.program_name} [options] <schema> <data>...")
+parser.separator("  #{parser.program_name} [options] <schema> -")
+parser.separator("  #{parser.program_name} [options] - <data>...")
+parser.separator("  #{parser.program_name} -h | --help")
+parser.separator("  #{parser.program_name} --version")
+parser.separator('')
+parser.separator('Options:')
+parser.on('-e', '--errors MAX', Integer, 'Maximum number of errors to output', 'Use "0" to validate with no output')
+parser.on_tail('-h', '--help', 'Show help')
+parser.on_tail('-v', '--version', 'Show version')
+
+options = {}
+parser.parse!(:into => options)
+
+if options[:help]
+  $stdout.puts(parser)
+  exit
+end
+
+if options[:version]
+  $stdout.puts("#{parser.program_name} #{JSONSchemer::VERSION}")
+  exit
+end
+
+if ARGV.size == 0
+  $stderr.puts("#{parser.program_name}: no schema or data")
+  exit(false)
+end
+
+if ARGV.size == 1
+  $stderr.puts("#{parser.program_name}: no data")
+  exit(false)
+end
+
+if ARGV.count('-') > 1
+  $stderr.puts("#{parser.program_name}: multiple stdin")
+  exit(false)
+end
+
+errors = 0
+schema = ARGF.file.is_a?(File) ? Pathname.new(ARGF.file.path) : ARGF.file.read
+schemer = JSONSchemer.schema(schema)
+
+while ARGV.any?
+  data = JSON.parse(ARGF.skip.file.read)
+  schemer.validate(data).each do |error|
+    exit(false) if options[:errors] == 0
+    errors += 1
+    $stdout.puts(JSON.generate(error))
+    exit(false) if options[:errors] == errors
+  end
+end
+
+exit(errors.zero?)
diff --git a/lib/json_schemer.rb b/lib/json_schemer.rb
index 869a624..5e9ea4d 100644
--- a/lib/json_schemer.rb
+++ b/lib/json_schemer.rb
@@ -1,9 +1,11 @@
 # frozen_string_literal: true
 require 'base64'
+require 'bigdecimal'
 require 'ipaddr'
 require 'json'
 require 'net/http'
 require 'pathname'
+require 'set'
 require 'time'
 require 'uri'
 
@@ -15,7 +17,7 @@ require 'uri_template'
 require 'json_schemer/version'
 require 'json_schemer/format'
 require 'json_schemer/errors'
-require 'json_schemer/cached_ref_resolver'
+require 'json_schemer/cached_resolver'
 require 'json_schemer/schema/base'
 require 'json_schemer/schema/draft4'
 require 'json_schemer/schema/draft6'
@@ -25,6 +27,7 @@ module JSONSchemer
   class UnsupportedMetaSchema < StandardError; end
   class UnknownRef < StandardError; end
   class InvalidRefResolution < StandardError; end
+  class InvalidRegexpResolution < StandardError; end
   class InvalidFileURI < StandardError; end
   class InvalidSymbolKey < StandardError; end
 
@@ -44,7 +47,7 @@ module JSONSchemer
     raise InvalidFileURI, 'cannot have a host (use `file:///`)' if uri.host && !uri.host.empty?
     path = uri.path
     path = path[1..-1] if path.match?(WINDOWS_URI_PATH_REGEX)
-    JSON.parse(File.read(path))
+    JSON.parse(File.read(URI::DEFAULT_PARSER.unescape(path)))
   end
 
   class << self
@@ -53,11 +56,11 @@ module JSONSchemer
       when String
         schema = JSON.parse(schema)
       when Pathname
-        uri = URI.parse(File.join('file:', schema.realpath))
+        uri = URI.parse(File.join('file:', URI::DEFAULT_PARSER.escape(schema.realpath.to_s)))
         if options.key?(:ref_resolver)
           schema = FILE_URI_REF_RESOLVER.call(uri)
         else
-          ref_resolver = CachedRefResolver.new(&FILE_URI_REF_RESOLVER)
+          ref_resolver = CachedResolver.new(&FILE_URI_REF_RESOLVER)
           schema = ref_resolver.call(uri)
           options[:ref_resolver] = ref_resolver
         end
diff --git a/lib/json_schemer/cached_ref_resolver.rb b/lib/json_schemer/cached_ref_resolver.rb
deleted file mode 100644
index 07152c2..0000000
--- a/lib/json_schemer/cached_ref_resolver.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-module JSONSchemer
-  class CachedRefResolver
-    def initialize(&ref_resolver)
-      @ref_resolver = ref_resolver
-      @cache = {}
-    end
-
-    def call(uri)
-      @cache[uri] = @ref_resolver.call(uri) unless @cache.key?(uri)
-      @cache[uri]
-    end
-  end
-end
diff --git a/lib/json_schemer/cached_resolver.rb b/lib/json_schemer/cached_resolver.rb
new file mode 100644
index 0000000..2e8a27b
--- /dev/null
+++ b/lib/json_schemer/cached_resolver.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+module JSONSchemer
+  class CachedResolver
+    def initialize(&resolver)
+      @resolver = resolver
+      @cache = {}
+    end
+
+    def call(*args)
+      @cache[args] = @resolver.call(*args) unless @cache.key?(args)
+      @cache[args]
+    end
+  end
+
+  class CachedRefResolver < CachedResolver; end
+end
diff --git a/lib/json_schemer/format.rb b/lib/json_schemer/format.rb
index 397c2e3..0ce90a4 100644
--- a/lib/json_schemer/format.rb
+++ b/lib/json_schemer/format.rb
@@ -60,7 +60,7 @@ module JSONSchemer
     def valid_date_time?(data)
       DateTime.rfc3339(data)
       DATE_TIME_OFFSET_REGEX.match?(data)
-    rescue ArgumentError => e
+    rescue ArgumentError
       false
     end
 
diff --git a/lib/json_schemer/schema/base.rb b/lib/json_schemer/schema/base.rb
index 599b23e..a2e91d0 100644
--- a/lib/json_schemer/schema/base.rb
+++ b/lib/json_schemer/schema/base.rb
@@ -30,12 +30,23 @@ module JSONSchemer
         :eol => '\z'
       }.freeze
 
+      ECMA_262_REGEXP_RESOLVER = proc do |pattern|
+        Regexp.new(
+          Regexp::Scanner.scan(pattern).map do |type, token, text|
+            type == :anchor ? RUBY_REGEX_ANCHORS_TO_ECMA_262.fetch(token, text) : text
+          end.join
+        )
+      end
+
       INSERT_DEFAULT_PROPERTY = proc do |data, property, property_schema, _parent|
         if !data.key?(property) && property_schema.is_a?(Hash) && property_schema.key?('default')
           data[property] = property_schema.fetch('default').clone
         end
       end
 
+      JSON_POINTER_TOKEN_ESCAPE_CHARS = { '~' => '~0', '/' => '~1' }
+      JSON_POINTER_TOKEN_ESCAPE_REGEXP = Regexp.union(JSON_POINTER_TOKEN_ESCAPE_CHARS.keys)
+
       def initialize(
         schema,
         format: true,
@@ -44,7 +55,8 @@ module JSONSchemer
         after_property_validation: nil,
         formats: nil,
         keywords: nil,
-        ref_resolver: DEFAULT_REF_RESOLVER
+        ref_resolver: DEFAULT_REF_RESOLVER,
+        regexp_resolver: 'ecma'
       )
         raise InvalidSymbolKey, 'schemas must use string keys' if schema.is_a?(Hash) && !schema.empty? && !schema.first.first.is_a?(String)
         @root = schema
@@ -54,7 +66,15 @@ module JSONSchemer
         @after_property_validation = [*after_property_validation]
         @formats = formats
         @keywords = keywords
-        @ref_resolver = ref_resolver == 'net/http' ? CachedRefResolver.new(&NET_HTTP_REF_RESOLVER) : ref_resolver
+        @ref_resolver = ref_resolver == 'net/http' ? CachedResolver.new(&NET_HTTP_REF_RESOLVER) : ref_resolver
+        @regexp_resolver = case regexp_resolver
+        when 'ecma'
+          CachedResolver.new(&ECMA_262_REGEXP_RESOLVER)
+        when 'ruby'
+          CachedResolver.new(&Regexp.method(:new))
+        else
+          regexp_resolver
+        end
       end
 
       def valid?(data)
@@ -204,7 +224,7 @@ module JSONSchemer
 
     private
 
-      attr_reader :root, :formats, :keywords, :ref_resolver
+      attr_reader :root, :formats, :keywords, :ref_resolver, :regexp_resolver
 
       def id_keyword
         ID_KEYWORD
@@ -228,7 +248,8 @@ module JSONSchemer
           format: format?,
           formats: formats,
           keywords: keywords,
-          ref_resolver: ref_resolver
+          ref_resolver: ref_resolver,
+          regexp_resolver: regexp_resolver
         )
       end
 
@@ -355,8 +376,7 @@ module JSONSchemer
         validate_exclusive_minimum(instance, exclusive_minimum, minimum, &block) if exclusive_minimum
 
         if multiple_of
-          quotient = data / multiple_of.to_f
-          yield error(instance, 'multipleOf') unless quotient.floor == quotient
+          yield error(instance, 'multipleOf') unless BigDecimal(data.to_s).modulo(multiple_of).zero?
         end
       end
 
@@ -399,7 +419,7 @@ module JSONSchemer
 
         yield error(instance, 'maxLength') if max_length && data.size > max_length
         yield error(instance, 'minLength') if min_length && data.size < min_length
-        yield error(instance, 'pattern') if pattern && ecma_262_regex(pattern) !~ data
+        yield error(instance, 'pattern') if pattern && !resolve_regexp(pattern).match?(data)
         yield error(instance, 'format') if format? && spec_format?(format) && !valid_spec_format?(data, format)
 
         if content_encoding || content_media_type
@@ -514,7 +534,8 @@ module JSONSchemer
           dependencies.each do |key, value|
             next unless data.key?(key)
             subschema = value.is_a?(Array) ? { 'required' => value } : value
-            subinstance = instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/dependencies/#{key}")
+            escaped_key = escape_json_pointer_token(key)
+            subinstance = instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/dependencies/#{escaped_key}")
             validate_instance(subinstance, &block)
           end
         end
@@ -528,6 +549,8 @@ module JSONSchemer
 
         regex_pattern_properties = nil
         data.each do |key, value|
+          escaped_key = escape_json_pointer_token(key)
+
           unless property_names.nil?
             subinstance = instance.merge(
               data: key,
@@ -542,9 +565,9 @@ module JSONSchemer
           if properties && properties.key?(key)
             subinstance = instance.merge(
               data: value,
-              data_pointer: "#{instance.data_pointer}/#{key}",
+              data_pointer: "#{instance.data_pointer}/#{escaped_key}",
               schema: properties[key],
-              schema_pointer: "#{instance.schema_pointer}/properties/#{key}"
+              schema_pointer: "#{instance.schema_pointer}/properties/#{escaped_key}"
             )
             validate_instance(subinstance, &block)
             matched_key = true
@@ -552,15 +575,16 @@ module JSONSchemer
 
           if pattern_properties
             regex_pattern_properties ||= pattern_properties.map do |pattern, property_schema|
-              [pattern, ecma_262_regex(pattern), property_schema]
+              [pattern, resolve_regexp(pattern), property_schema]
             end
             regex_pattern_properties.each do |pattern, regex, property_schema|
+              escaped_pattern = escape_json_pointer_token(pattern)
               if regex.match?(key)
                 subinstance = instance.merge(
                   data: value,
-                  data_pointer: "#{instance.data_pointer}/#{key}",
+                  data_pointer: "#{instance.data_pointer}/#{escaped_key}",
                   schema: property_schema,
-                  schema_pointer: "#{instance.schema_pointer}/patternProperties/#{pattern}"
+                  schema_pointer: "#{instance.schema_pointer}/patternProperties/#{escaped_pattern}"
                 )
                 validate_instance(subinstance, &block)
                 matched_key = true
@@ -573,7 +597,7 @@ module JSONSchemer
           unless additional_properties.nil?
             subinstance = instance.merge(
               data: value,
-              data_pointer: "#{instance.data_pointer}/#{key}",
+              data_pointer: "#{instance.data_pointer}/#{escaped_key}",
               schema: additional_properties,
               schema_pointer: "#{instance.schema_pointer}/additionalProperties"
             )
@@ -597,13 +621,8 @@ module JSONSchemer
         nil
       end
 
-      def ecma_262_regex(pattern)
-        @ecma_262_regex ||= {}
-        @ecma_262_regex[pattern] ||= Regexp.new(
-          Regexp::Scanner.scan(pattern).map do |type, token, text|
-            type == :anchor ? RUBY_REGEX_ANCHORS_TO_ECMA_262.fetch(token, text) : text
-          end.join
-        )
+      def escape_json_pointer_token(token)
+        token.gsub(JSON_POINTER_TOKEN_ESCAPE_REGEXP, JSON_POINTER_TOKEN_ESCAPE_CHARS)
       end
 
       def join_uri(a, b)
@@ -653,6 +672,10 @@ module JSONSchemer
       def resolve_ref(uri)
         ref_resolver.call(uri) || raise(InvalidRefResolution, uri.to_s)
       end
+
+      def resolve_regexp(pattern)
+        regexp_resolver.call(pattern) || raise(InvalidRegexpResolution, pattern)
+      end
     end
   end
 end
diff --git a/lib/json_schemer/version.rb b/lib/json_schemer/version.rb
index 61adddd..580e32f 100644
--- a/lib/json_schemer/version.rb
+++ b/lib/json_schemer/version.rb
@@ -1,4 +1,4 @@
 # frozen_string_literal: true
 module JSONSchemer
-  VERSION = '0.2.18'
+  VERSION = '0.2.24'
 end
diff --git a/test/benchmark.rb b/test/benchmark.rb
new file mode 100644
index 0000000..93a7454
--- /dev/null
+++ b/test/benchmark.rb
@@ -0,0 +1,190 @@
+# frozen_string_literal: true
+$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
+
+require 'benchmark/ips'
+require 'jschema'
+require 'json-schema'
+require 'json_schema'
+require 'json_schemer'
+require 'json_validation'
+require 'rj_schema'
+# require 'jsonschema'
+
+# json_validation
+require 'digest'
+
+benchmarks = {
+  'simple' => {
+    'schema' => {
+      'type' => 'object',
+      'properties' => {
+        'firstName' => {
+          'type' => 'string'
+        },
+        'lastName' => {
+          'type' => 'string'
+        },
+        'age' => {
+          'type' => 'integer',
+          'minimum' => 0
+        }
+      },
+      'required' => [
+        'firstName',
+        'lastName'
+      ]
+    },
+    'valid' => {
+      'firstName' => 'Jean-Luc',
+      'lastName' => 'Picard',
+      'age' => 51
+    },
+    'invalid' => {
+      'lastName' => 'Janeway',
+      'age' => 41.1
+    }
+  }
+}
+
+Benchmark.ips do |x|
+  benchmarks.each do |name, defn|
+    schema, valid, invalid = defn.values_at('schema', 'valid', 'invalid')
+
+    initialized_jschema = JSchema.build(schema)
+    initialized_json_schema = JsonSchema.parse!(schema).tap(&:expand_references!)
+    initialized_json_schemer = JSONSchemer.schema(schema)
+    initialized_json_validation = JsonValidation.build_validator(schema)
+    initialized_rj_schema = RjSchema::Validator.new('schema' => schema)
+
+    # jschema
+
+    x.report("jschema, uninitialized, #{name}, valid") do
+      errors = JSchema.build(schema).validate(valid)
+      raise if errors.any?
+    end
+
+    x.report("jschema, uninitialized, #{name}, invalid") do
+      errors = JSchema.build(schema).validate(invalid)
+      raise if errors.empty?
+    end
+
+    x.report("jschema, initialized, #{name}, valid") do
+      errors = initialized_jschema.validate(valid)
+      raise if errors.any?
+    end
+
+    x.report("jschema, initialized, #{name}, invalid") do
+      errors = initialized_jschema.validate(invalid)
+      raise if errors.empty?
+    end
+
+    # json-schema
+
+    x.report("json-schema, #{name}, valid") do
+      raise unless JSON::Validator.validate(schema, valid)
+    end
+
+    x.report("json-schema, #{name}, invalid") do
+      raise if JSON::Validator.validate(schema, invalid)
+    end
+
+    # json_schema
+
+    x.report("json_schema, uninitialized, #{name}, valid") do
+      success, errors = JsonSchema.parse!(schema).tap(&:expand_references!).validate(valid)
+      raise if !success || errors.any?
+    end
+
+    x.report("json_schema, uninitialized, #{name}, invalid") do
+      success, errors = JsonSchema.parse!(schema).tap(&:expand_references!).validate(invalid)
+      raise if success || errors.empty?
+    end
+
+    x.report("json_schema, initialized, #{name}, valid") do
+      success, errors = initialized_json_schema.validate(valid)
+      raise if !success || errors.any?
+    end
+
+    x.report("json_schema, initialized, #{name}, invalid") do
+      success, errors = initialized_json_schema.validate(invalid)
+      raise if success || errors.empty?
+    end
+
+    # json_schemer
+
+    x.report("json_schemer, uninitialized, #{name}, valid") do
+      errors = JSONSchemer.schema(schema).validate(valid).to_a
+      raise if errors.any?
+    end
+
+    x.report("json_schemer, uninitialized, #{name}, invalid") do
+      errors = JSONSchemer.schema(schema).validate(invalid).to_a
+      raise if errors.empty?
+    end
+
+    x.report("json_schemer, initialized, #{name}, valid") do
+      errors = initialized_json_schemer.validate(valid).to_a
+      raise if errors.any?
+    end
+
+    x.report("json_schemer, initialized, #{name}, invalid") do
+      errors = initialized_json_schemer.validate(invalid).to_a
+      raise if errors.empty?
+    end
+
+    # json_validation
+
+    x.report("json_validation, uninitialized, #{name}, valid") do
+      raise unless JsonValidation.build_validator(schema).validate(valid)
+    end
+
+    x.report("json_validation, uninitialized, #{name}, invalid") do
+      raise if JsonValidation.build_validator(schema).validate(invalid)
+    end
+
+    x.report("json_validation, initialized, #{name}, valid") do
+      raise unless initialized_json_validation.validate(valid)
+    end
+
+    x.report("json_validation, initialized, #{name}, invalid") do
+      raise if initialized_json_validation.validate(invalid)
+    end
+
+    # rj_schema
+
+    x.report("rj_schema, uninitialized, #{name}, valid") do
+      errors = RjSchema::Validator.new.validate(schema, valid)
+      raise if errors.any?
+    end
+
+    x.report("rj_schema, uninitialized, #{name}, invalid") do
+      errors = RjSchema::Validator.new.validate(schema, invalid)
+      raise if errors.empty?
+    end
+
+    x.report("rj_schema, initialized, #{name}, valid") do
+      errors = initialized_rj_schema.validate(:"schema", valid)
+      raise if errors.any?
+    end
+
+    x.report("rj_schema, initialized, #{name}, invalid") do
+      errors = initialized_rj_schema.validate(:"schema", invalid)
+      raise if errors.empty?
+    end
+
+    # jsonschema
+
+    # x.report("jsonschema, #{name}, valid") do
+    #   JSON::Schema.validate(valid, schema)
+    # end
+
+    # x.report("jsonschema, #{name}, invalid") do
+    #   JSON::Schema.validate(invalid, schema)
+    # rescue JSON::Schema::ValueError
+    # else
+    #   raise
+    # end
+  end
+
+  x.compare!
+end
diff --git a/test/exe_test.rb b/test/exe_test.rb
new file mode 100644
index 0000000..992ec4d
--- /dev/null
+++ b/test/exe_test.rb
@@ -0,0 +1,199 @@
+require 'test_helper'
+require 'open3'
+
+class ExeTest < Minitest::Test
+  GEM_PATH = File.join(__dir__, '..', 'tmp', 'gems')
+  CMD = File.join(GEM_PATH, 'bin', 'json_schemer')
+  SCHEMA1 = File.join(__dir__, 'schemas', 'schema1.json')
+  VALID = { 'id' => 1, 'a' => 'valid' }
+  INVALID1 = { 'a' => 'invalid' }
+  INVALID2 = { 'id' => 1 }
+  INVALID3 = { 'id' => 1, 'a' => -1 }
+  INVALID4 = { 'id' => 'invalid', 'a' => 'valid' }
+  INVALID5 = { 'x' => 'invalid' }
+
+  def test_help
+    stdout, stderr, status = exe('-h')
+    assert_predicate(status, :success?)
+    assert_empty(stderr)
+    assert_includes(stdout, 'json_schemer [options]')
+    assert_includes(stdout, '-e, --errors MAX')
+    assert_includes(stdout, '-h, --help')
+    assert_includes(stdout, '-v, --version')
+  end
+
+  def test_version
+    stdout, stderr, status = exe('--version')
+    assert_predicate(status, :success?)
+    assert_empty(stderr)
+    assert_includes(stdout, JSONSchemer::VERSION)
+  end
+
+  def test_errors
+    stdout, stderr, status = exe
+    refute_predicate(status, :success?)
+    assert_includes(stderr, 'json_schemer: no schema or data')
+    assert_empty(stdout)
+
+    stdout, stderr, status = exe(SCHEMA1)
+    refute_predicate(status, :success?)
+    assert_includes(stderr, 'json_schemer: no data')
+    assert_empty(stdout)
+
+    stdout, stderr, status = exe('-', SCHEMA1, '-')
+    refute_predicate(status, :success?)
+    assert_includes(stderr, 'json_schemer: multiple stdin')
+    assert_empty(stdout)
+  end
+
+  def test_success
+    tmp_json(VALID) do |path|
+      stdout, stderr, status = exe(SCHEMA1, path)
+      assert_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe('--errors', '0', SCHEMA1, path)
+      assert_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe('--errors', '1', SCHEMA1, path)
+      assert_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+    end
+  end
+
+  def test_error_output
+    stdout, stderr, status = tmp_json(VALID, INVALID1, INVALID2, INVALID3, INVALID4, INVALID5) do |*paths|
+      exe(SCHEMA1, *paths)
+    end
+    refute_predicate(status, :success?)
+    assert_empty(stderr)
+    errors = stdout.each_line("\n", :chomp => true).map do |line|
+      JSON.parse(line).select { |key, _| ['data', 'type', 'details'].include?(key) }
+    end
+    assert_equal(6, errors.size)
+    assert_includes(errors, 'data' => INVALID1, 'type' => 'required', 'details' => { 'missing_keys' => ['id'] })
+    assert_includes(errors, 'data' => INVALID2, 'type' => 'required', 'details' => { 'missing_keys' => ['a'] })
+    assert_includes(errors, 'data' => INVALID3['a'], 'type' => 'string')
+    assert_includes(errors, 'data' => INVALID4['id'], 'type' => 'integer')
+    assert_includes(errors, 'data' => INVALID5, 'type' => 'required', 'details' => { 'missing_keys' => ['id'] })
+    assert_includes(errors, 'data' => INVALID5, 'type' => 'required', 'details' => { 'missing_keys' => ['a'] })
+  end
+
+  def test_max_errors
+    tmp_json(INVALID1, INVALID2, INVALID3, INVALID4, INVALID5) do |*paths|
+      stdout, stderr, status = exe('-e0', SCHEMA1, *paths)
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe('--errors', '0', SCHEMA1, *paths)
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe('--errors', '1', SCHEMA1, *paths)
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_equal(1, stdout.split("\n").size)
+
+      stdout, stderr, status = exe('--errors', '2', SCHEMA1, *paths)
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_equal(2, stdout.split("\n").size)
+
+      stdout, stderr, status = exe('-e2', SCHEMA1, *paths)
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_equal(2, stdout.split("\n").size)
+
+      stdout, stderr, status = exe('--errors', '10', SCHEMA1, *paths)
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_equal(6, stdout.split("\n").size)
+    end
+  end
+
+  def test_stdin
+    schema = {
+      'type' => 'object',
+      'properties' => {
+        'id' => {
+          'type' => 'integer'
+        }
+      }
+    }
+    valid_data = { 'id' => 1 }
+    invalid_data = { 'id' => 'invalid' }
+
+    tmp_json(schema, valid_data, invalid_data) do |schema_path, valid_path, invalid_path|
+      stdout, stderr, status = exe('-', valid_path, :stdin_data => JSON.generate(schema))
+      assert_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe('-', valid_path, invalid_path, :stdin_data => JSON.generate(schema))
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      refute_empty(stdout)
+
+      stdout, stderr, status = exe(schema_path, valid_path, '-', :stdin_data => JSON.generate(valid_data))
+      assert_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe(schema_path, valid_path, '-', :stdin_data => JSON.generate(invalid_data))
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      refute_empty(stdout)
+
+      stdout, stderr, status = exe('-e0', schema_path, invalid_path, '-', :stdin_data => JSON.generate(valid_data))
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe(schema_path, '-', valid_path, :stdin_data => JSON.generate(valid_data))
+      assert_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+
+      stdout, stderr, status = exe(schema_path, '-', valid_path, :stdin_data => JSON.generate(invalid_data))
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      refute_empty(stdout)
+
+      stdout, stderr, status = exe('-e0', schema_path, '-', invalid_path, :stdin_data => JSON.generate(valid_data))
+      refute_predicate(status, :success?)
+      assert_empty(stderr)
+      assert_empty(stdout)
+    end
+  end
+
+private
+
+  def exe(*args, **kwargs)
+    env = {
+      'GEM_HOME' => Gem.dir,
+      'GEM_PATH' => [GEM_PATH, *Gem.path].uniq.join(File::PATH_SEPARATOR),
+      'GEM_SPEC_CACHE' => Gem.spec_cache_dir,
+      'RUBYOPT' => nil # prevent bundler/setup
+    }
+    Open3.capture3(env, CMD, *args, **kwargs)
+  end
+
+  def tmp_json(*json)
+    files = json.map do |data, index|
+      file = Tempfile.new(['data', '.json'])
+      file.sync = true
+      file.write(JSON.generate(data))
+      file
+    end
+    yield(*files.map(&:path))
+  ensure
+    files.each(&:close)
+    files.each(&:unlink)
+  end
+end
diff --git a/test/fixtures/draft4.json b/test/fixtures/draft4.json
new file mode 100644
index 0000000..d700cc6
--- /dev/null
+++ b/test/fixtures/draft4.json
@@ -0,0 +1,7785 @@
+{
+  "JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            1.0,
+            1.0,
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": "bar"
+            },
+            {
+              "foo": "bar"
+            }
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": {
+                "bar": {
+                  "baz": true
+                }
+              }
+            },
+            {
+              "foo": {
+                "bar": {
+                  "baz": true
+                }
+              }
+            }
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            [
+              "foo"
+            ],
+            [
+              "foo"
+            ]
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+            },
+            [
+              1
+            ],
+            true,
+            null,
+            {
+            },
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            false
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            true
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            true,
+            "foo",
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            false,
+            "foo",
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            false
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            true
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "/2",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "schema"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/minItems.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "minItems": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minItems": 1
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "boom",
+          "data_pointer": "/quux",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "patternProperties": {
+              "^v": {
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/élmény",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "patternProperties": {
+              "^á": {
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 12,
+          "data_pointer": "/quux",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                  }
+                }
+              }
+            ],
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/dependencies.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": [
+                "foo"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "quux": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 1,
+            "quux": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "quux": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo",
+              "bar"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/foo",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/foo",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo\nbar": 1,
+            "foo": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\rbar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo\nbar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\rbar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo\tbar": 1,
+            "a": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "minProperties": 4
+          },
+          "schema_pointer": "/dependencies/foo\tbar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "minProperties"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo'bar": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\"bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo'bar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\"bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo\"bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo'bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo\"bar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo'bar"
+            ]
+          }
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/anyOf.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 2
+          },
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 2
+          },
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "maxLength"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 4
+          },
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "minLength"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/anyOf/0/properties/bar",
+          "root_schema": {
+            "anyOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/anyOf/1/properties/foo",
+          "root_schema": {
+            "anyOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "/anyOf/0/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            ]
+          },
+          "type": "null"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/not.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": "integer"
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "boolean"
+            ]
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": [
+                "integer",
+                "boolean"
+              ]
+            }
+          },
+          "type": "not"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "boolean"
+            ]
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": [
+                "integer",
+                "boolean"
+              ]
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            }
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": "object",
+              "properties": {
+                "foo": {
+                  "type": "string"
+                }
+              }
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+          },
+          "schema_pointer": "/properties/foo/not",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "not": {
+                }
+              }
+            }
+          },
+          "type": "not"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/items.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "x",
+          "data_pointer": "/1",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items/0",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1,
+          "data_pointer": "/1",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/items/1",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": null
+            },
+            {
+              "foo": null
+            }
+          ],
+          "data_pointer": "/3",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": null
+          },
+          "data_pointer": "/0/2",
+          "schema": false,
+          "schema_pointer": "/definitions/item/additionalItems",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": null
+          },
+          "data_pointer": "/0",
+          "schema": {
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/sub-item"
+              },
+              {
+                "$ref": "#/definitions/sub-item"
+              }
+            ]
+          },
+          "schema_pointer": "/definitions/item",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "/0/0",
+          "schema": {
+            "type": "object",
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/definitions/sub-item",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/0/0/0/0",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/items/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "/0/0/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/0/1/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 3,
+          "data_pointer": "/0/2/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 4,
+          "data_pointer": "/1/0/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 5,
+          "data_pointer": "/1/1/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 6,
+          "data_pointer": "/1/2/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/enum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 4,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              1,
+              2,
+              3
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              1,
+              2,
+              3
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": false
+          },
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "foo"
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              "foo\nbar",
+              "foo\rbar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              "foo\nbar",
+              "foo\rbar"
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              false
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": 0.0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              false
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              true
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": 1.0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              true
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              0
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              0
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              1
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              1
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/minProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "minProperties": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minProperties": 1
+          },
+          "type": "minProperties"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/properties.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": {
+          },
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "array",
+            "maxItems": 3
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "maxItems"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "minItems": 2
+          },
+          "schema_pointer": "/patternProperties/f.o",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/fxo",
+          "schema": {
+            "minItems": 2
+          },
+          "schema_pointer": "/patternProperties/f.o",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/quux",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/foo\nbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\nbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\"bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\"bar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\\bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\\bar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\rbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\rbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\tbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\tbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\fbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\fbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/maxLength.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxLength": 2
+          },
+          "type": "maxLength"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/minimum.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 0.6,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": 1.1
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 0.6,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 1.1,
+            "exclusiveMinimum": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": 1.1,
+            "exclusiveMinimum": false
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 1.1,
+            "exclusiveMinimum": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": 1.1,
+            "exclusiveMinimum": true
+          },
+          "type": "exclusiveMinimum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": -3,
+          "data_pointer": "",
+          "schema": {
+            "minimum": -2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": -2
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/optional/zeroTerminatedFloats.json": [
+    [
+      [
+        {
+          "data": 1.0,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/optional/bignum.json": [
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 98249283749234923498293171823948729348710298301928331,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 9.727837981879871e+26,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 9.727837981879871e+26,
+            "exclusiveMaximum": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maximum": 9.727837981879871e+26,
+            "exclusiveMaximum": true
+          },
+          "type": "exclusiveMaximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": -9.727837981879871e+26,
+          "data_pointer": "",
+          "schema": {
+            "minimum": -9.727837981879871e+26,
+            "exclusiveMinimum": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": -9.727837981879871e+26,
+            "exclusiveMinimum": true
+          },
+          "type": "exclusiveMinimum"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/optional/ecmascript-regex.json": [
+    [
+      [
+        {
+          "data": "^\\S(|(.|\\n)*\\S)\\Z",
+          "data_pointer": "",
+          "schema": {
+            "format": "regex"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "regex"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "abc\n",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^abc$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\a",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\cC",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\cc",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "߀",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+        {
+          "data": "߀",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "0",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "é",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": " ",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": " ",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/optional/format.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "1990-02-31T15:59:60.123-08:00",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1990-12-31T15:59:60-24:00",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "06/19/1963 08:30:06 PST",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "2013-350T01:01:01",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "//foo.bar/?baz=qux#quux",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\fileshare",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "http:// shouldfail.com",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": ":// should fail",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "2962",
+          "data_pointer": "",
+          "schema": {
+            "format": "email"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "email"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "127.0.0.0.1",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "256.256.256.256",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "127.0",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "0x7f000001",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "12345::",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "::laptop",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "-a-host-name-that-starts-with--",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "not_a_valid_host_name",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/oneOf.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ],
+      [
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 2
+          },
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "oneOf"
+        },
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "baz",
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/oneOf/0/properties/bar",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/oneOf/1/properties/foo",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        },
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "baz"
+            ]
+          },
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo",
+              "baz"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2,
+            "baz": 3
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/additionalItems.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/3",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+              }
+            ],
+            "additionalItems": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 4,
+          "data_pointer": "/3",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+              },
+              {
+              },
+              {
+              }
+            ],
+            "additionalItems": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/pattern.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "pattern": "^a*$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "pattern": "^a*$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/definitions.json": [
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/definitions/foo/type",
+          "schema": {
+            "enum": [
+              "array",
+              "boolean",
+              "integer",
+              "null",
+              "number",
+              "object",
+              "string"
+            ]
+          },
+          "schema_pointer": "/definitions/simpleTypes",
+          "root_schema": {
+            "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"
+              },
+              "$schema": {
+                "type": "string"
+              },
+              "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
+                  }
+                ]
+              },
+              "format": {
+                "type": "string"
+              },
+              "allOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "anyOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "oneOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "not": {
+                "$ref": "#"
+              }
+            },
+            "dependencies": {
+              "exclusiveMaximum": [
+                "maximum"
+              ],
+              "exclusiveMinimum": [
+                "minimum"
+              ]
+            },
+            "default": {
+            }
+          },
+          "type": "enum"
+        },
+        {
+          "data": 1,
+          "data_pointer": "/definitions/foo/type",
+          "schema": {
+            "type": "array",
+            "items": {
+              "$ref": "#/definitions/simpleTypes"
+            },
+            "minItems": 1,
+            "uniqueItems": true
+          },
+          "schema_pointer": "/properties/type/anyOf/1",
+          "root_schema": {
+            "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"
+              },
+              "$schema": {
+                "type": "string"
+              },
+              "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
+                  }
+                ]
+              },
+              "format": {
+                "type": "string"
+              },
+              "allOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "anyOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "oneOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "not": {
+                "$ref": "#"
+              }
+            },
+            "dependencies": {
+              "exclusiveMaximum": [
+                "maximum"
+              ],
+              "exclusiveMinimum": [
+                "minimum"
+              ]
+            },
+            "default": {
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/maxProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2,
+            "baz": 3
+          },
+          "data_pointer": "",
+          "schema": {
+            "maxProperties": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxProperties": 2
+          },
+          "type": "maxProperties"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/required.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo\nbar": "1",
+            "foo\"bar": "1"
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\nbar",
+              "foo\"bar",
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "required": [
+              "foo\nbar",
+              "foo\"bar",
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          }
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/type.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": "",
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": "",
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/default.json": [
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/multipleOf.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 7,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 2
+          },
+          "type": "multipleOf"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 35,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 1.5
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 1.5
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0.00751,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 0.0001
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 0.0001
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/patternProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": "baz",
+          "data_pointer": "/foooooo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/a",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/a*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": 31,
+          "data_pointer": "/aaaa",
+          "schema": {
+            "maximum": 20
+          },
+          "schema_pointer": "/patternProperties/aaa*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/aaa",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/a*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": 31,
+          "data_pointer": "/aaaa",
+          "schema": {
+            "maximum": 20
+          },
+          "schema_pointer": "/patternProperties/aaa*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "maximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "/a31b",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/patternProperties/[0-9]{2,}",
+          "root_schema": {
+            "patternProperties": {
+              "[0-9]{2,}": {
+                "type": "boolean"
+              },
+              "X_": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "/a_X_3",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/patternProperties/X_",
+          "root_schema": {
+            "patternProperties": {
+              "[0-9]{2,}": {
+                "type": "boolean"
+              },
+              "X_": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/refRemote.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/integer",
+          "root_schema": {
+            "integer": {
+              "type": "integer"
+            },
+            "refToInteger": {
+              "$ref": "#/integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/integer",
+          "root_schema": {
+            "integer": {
+              "type": "integer"
+            },
+            "refToInteger": {
+              "$ref": "#/integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/0/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/list/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/list/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "name": null
+          },
+          "data_pointer": "/name",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "/definitions/orNull/anyOf/0",
+          "root_schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "type": "null"
+        },
+        {
+          "data": {
+            "name": null
+          },
+          "data_pointer": "/name",
+          "schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/allOf.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "baz"
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/allOf/0/properties/bar",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "quux",
+            "baz": null
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2,
+            "baz": null
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": "quux",
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "baz": {
+                "type": "null"
+              }
+            },
+            "required": [
+              "baz"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "baz"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        },
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "baz": {
+                "type": "null"
+              }
+            },
+            "required": [
+              "baz"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "baz"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 35,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 30
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "maximum": 30
+              },
+              {
+                "minimum": 20
+              }
+            ]
+          },
+          "type": "maximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              {
+              },
+              {
+                "type": "number"
+              }
+            ]
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "type": "number"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/format.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/ref.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "$ref": "#"
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "/foo/bar",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "$ref": "#"
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "$ref": "#/properties/foo"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items/0",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "$ref": "#/items/0"
+              }
+            ]
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/slash",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/slash~1field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/tilda",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/tilda~0field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/percent",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/percent%25field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/a",
+          "root_schema": {
+            "definitions": {
+              "a": {
+                "type": "integer"
+              },
+              "b": {
+                "$ref": "#/definitions/a"
+              },
+              "c": {
+                "$ref": "#/definitions/b"
+              }
+            },
+            "$ref": "#/definitions/c"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "string",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "/definitions/reffed",
+          "root_schema": {
+            "definitions": {
+              "reffed": {
+                "type": "array"
+              }
+            },
+            "properties": {
+              "foo": {
+                "$ref": "#/definitions/reffed",
+                "maxItems": 2
+              }
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": -1,
+          "data_pointer": "/minLength",
+          "schema": {
+            "type": "integer",
+            "minimum": 0
+          },
+          "schema_pointer": "/definitions/positiveInteger",
+          "root_schema": {
+            "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"
+              },
+              "$schema": {
+                "type": "string"
+              },
+              "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
+                  }
+                ]
+              },
+              "format": {
+                "type": "string"
+              },
+              "allOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "anyOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "oneOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "not": {
+                "$ref": "#"
+              }
+            },
+            "dependencies": {
+              "exclusiveMaximum": [
+                "maximum"
+              ],
+              "exclusiveMinimum": [
+                "minimum"
+              ]
+            },
+            "default": {
+            }
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/$ref",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/$ref",
+          "root_schema": {
+            "properties": {
+              "$ref": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "string is invalid",
+          "data_pointer": "/nodes/0/subtree/nodes/0/value",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/definitions/node/properties/value",
+          "root_schema": {
+            "id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+              "meta": {
+                "type": "string"
+              },
+              "nodes": {
+                "type": "array",
+                "items": {
+                  "$ref": "node"
+                }
+              }
+            },
+            "required": [
+              "meta",
+              "nodes"
+            ],
+            "definitions": {
+              "node": {
+                "id": "http://localhost:1234/node",
+                "description": "node",
+                "type": "object",
+                "properties": {
+                  "value": {
+                    "type": "number"
+                  },
+                  "subtree": {
+                    "$ref": "tree"
+                  }
+                },
+                "required": [
+                  "value"
+                ]
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/foo\"bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/definitions/foo%22bar",
+          "root_schema": {
+            "properties": {
+              "foo\"bar": {
+                "$ref": "#/definitions/foo%22bar"
+              }
+            },
+            "definitions": {
+              "foo\"bar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "id": "#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A",
+          "root_schema": {
+            "allOf": [
+              {
+                "$ref": "#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "id": "#foo",
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "id": "http://localhost:1234/bar#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A",
+          "root_schema": {
+            "allOf": [
+              {
+                "$ref": "http://localhost:1234/bar#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "id": "http://localhost:1234/bar#foo",
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "id": "#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A/definitions/B",
+          "root_schema": {
+            "id": "http://localhost:1234/root",
+            "allOf": [
+              {
+                "$ref": "http://localhost:1234/nested.json#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "id": "nested.json",
+                "definitions": {
+                  "B": {
+                    "id": "#foo",
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/maximum.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3.5,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maximum": 3.0
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3.5,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 3.0,
+            "exclusiveMaximum": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maximum": 3.0,
+            "exclusiveMaximum": false
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 3.0,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 3.0,
+            "exclusiveMaximum": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maximum": 3.0,
+            "exclusiveMaximum": true
+          },
+          "type": "exclusiveMaximum"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/minLength.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "f",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minLength": 2
+          },
+          "type": "minLength"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "💩",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minLength": 2
+          },
+          "type": "minLength"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft4/maxItems.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3
+          ],
+          "data_pointer": "",
+          "schema": {
+            "maxItems": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxItems": 2
+          },
+          "type": "maxItems"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ]
+}
diff --git a/test/fixtures/draft6.json b/test/fixtures/draft6.json
new file mode 100644
index 0000000..5e354ea
--- /dev/null
+++ b/test/fixtures/draft6.json
@@ -0,0 +1,9170 @@
+{
+  "JSON-Schema-Test-Suite/tests/draft6/uniqueItems.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            1.0,
+            1.0,
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": "bar"
+            },
+            {
+              "foo": "bar"
+            }
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": {
+                "bar": {
+                  "baz": true
+                }
+              }
+            },
+            {
+              "foo": {
+                "bar": {
+                  "baz": true
+                }
+              }
+            }
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            [
+              "foo"
+            ],
+            [
+              "foo"
+            ]
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+            },
+            [
+              1
+            ],
+            true,
+            null,
+            {
+            },
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            false
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            true
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            true,
+            "foo",
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            false,
+            "foo",
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            false
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            true
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "/2",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "schema"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/minItems.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "minItems": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minItems": 1
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/additionalProperties.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "boom",
+          "data_pointer": "/quux",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "patternProperties": {
+              "^v": {
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/élmény",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "patternProperties": {
+              "^á": {
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 12,
+          "data_pointer": "/quux",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                  }
+                }
+              }
+            ],
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/dependencies.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": [
+                "foo"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "quux": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 1,
+            "quux": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "quux": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo",
+              "bar"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/foo",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/foo",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo\nbar": 1,
+            "foo": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\rbar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo\nbar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\rbar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo\tbar": 1,
+            "a": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "minProperties": 4
+          },
+          "schema_pointer": "/dependencies/foo\tbar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "minProperties"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo'bar": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\"bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo'bar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\"bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo\"bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo'bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo\"bar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo'bar"
+            ]
+          }
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/exclusiveMinimum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "type": "exclusiveMinimum"
+        }
+      ],
+      [
+        {
+          "data": 0.6,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "type": "exclusiveMinimum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/const.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 5,
+          "data_pointer": "",
+          "schema": {
+            "const": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 2
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "const": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 2
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": [
+            1,
+            2
+          ],
+          "data_pointer": "",
+          "schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            2
+          ],
+          "data_pointer": "",
+          "schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3
+          ],
+          "data_pointer": "",
+          "schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "const": null
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": null
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "const": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": false
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": 0.0,
+          "data_pointer": "",
+          "schema": {
+            "const": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": false
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "const": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": true
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": 1.0,
+          "data_pointer": "",
+          "schema": {
+            "const": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": true
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "const": 0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 0
+          },
+          "type": "const"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "const": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 1
+          },
+          "type": "const"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/anyOf.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 2
+          },
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 2
+          },
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "maxLength"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 4
+          },
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "minLength"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "anyOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/anyOf/0/properties/bar",
+          "root_schema": {
+            "anyOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/anyOf/1/properties/foo",
+          "root_schema": {
+            "anyOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "/anyOf/0/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            ]
+          },
+          "type": "null"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/propertyNames.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foobar",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 3
+          },
+          "schema_pointer": "/propertyNames",
+          "root_schema": {
+            "propertyNames": {
+              "maxLength": 3
+            }
+          },
+          "type": "maxLength"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/propertyNames",
+          "root_schema": {
+            "propertyNames": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/boolean_schema.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": [
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/not.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": "integer"
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "boolean"
+            ]
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": [
+                "integer",
+                "boolean"
+              ]
+            }
+          },
+          "type": "not"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "boolean"
+            ]
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": [
+                "integer",
+                "boolean"
+              ]
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            }
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": "object",
+              "properties": {
+                "foo": {
+                  "type": "string"
+                }
+              }
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+          },
+          "schema_pointer": "/properties/foo/not",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "not": {
+                }
+              }
+            }
+          },
+          "type": "not"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": true,
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": true
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/items.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "x",
+          "data_pointer": "/1",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items/0",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1,
+          "data_pointer": "/1",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/items/1",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/0",
+          "schema": false,
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": false
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": false,
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": false
+          },
+          "type": "schema"
+        },
+        {
+          "data": true,
+          "data_pointer": "/2",
+          "schema": false,
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": false,
+          "schema_pointer": "/items/1",
+          "root_schema": {
+            "items": [
+              true,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": null
+            },
+            {
+              "foo": null
+            }
+          ],
+          "data_pointer": "/3",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": null
+          },
+          "data_pointer": "/0/2",
+          "schema": false,
+          "schema_pointer": "/definitions/item/additionalItems",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": null
+          },
+          "data_pointer": "/0",
+          "schema": {
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/sub-item"
+              },
+              {
+                "$ref": "#/definitions/sub-item"
+              }
+            ]
+          },
+          "schema_pointer": "/definitions/item",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "/0/0",
+          "schema": {
+            "type": "object",
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/definitions/sub-item",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/0/0/0/0",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/items/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "/0/0/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/0/1/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 3,
+          "data_pointer": "/0/2/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 4,
+          "data_pointer": "/1/0/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 5,
+          "data_pointer": "/1/1/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 6,
+          "data_pointer": "/1/2/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/enum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 4,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              1,
+              2,
+              3
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              1,
+              2,
+              3
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": false
+          },
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "foo"
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              "foo\nbar",
+              "foo\rbar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              "foo\nbar",
+              "foo\rbar"
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              false
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": 0.0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              false
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              true
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": 1.0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              true
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              0
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              0
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              1
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              1
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/minProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "minProperties": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minProperties": 1
+          },
+          "type": "minProperties"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/properties.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": {
+          },
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "array",
+            "maxItems": 3
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "maxItems"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "minItems": 2
+          },
+          "schema_pointer": "/patternProperties/f.o",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/fxo",
+          "schema": {
+            "minItems": 2
+          },
+          "schema_pointer": "/patternProperties/f.o",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/quux",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/foo\nbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\nbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\"bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\"bar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\\bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\\bar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\rbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\rbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\tbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\tbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\fbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\fbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/maxLength.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxLength": 2
+          },
+          "type": "maxLength"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/exclusiveMaximum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 3.0,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "type": "exclusiveMaximum"
+        }
+      ],
+      [
+        {
+          "data": 3.5,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "type": "exclusiveMaximum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/minimum.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 0.6,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": 1.1
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": -3,
+          "data_pointer": "",
+          "schema": {
+            "minimum": -2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": -2
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/optional/zeroTerminatedFloats.json": [
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/optional/bignum.json": [
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 98249283749234923498293171823948729348710298301928331,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 9.727837981879871e+26,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMaximum": 9.727837981879871e+26
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMaximum": 9.727837981879871e+26
+          },
+          "type": "exclusiveMaximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": -9.727837981879871e+26,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMinimum": -9.727837981879871e+26
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMinimum": -9.727837981879871e+26
+          },
+          "type": "exclusiveMinimum"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/optional/ecmascript-regex.json": [
+    [
+      [
+        {
+          "data": "^\\S(|(.|\\n)*\\S)\\Z",
+          "data_pointer": "",
+          "schema": {
+            "format": "regex"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "regex"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "abc\n",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^abc$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\a",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\cC",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\cc",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "߀",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+        {
+          "data": "߀",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "0",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "é",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": " ",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": " ",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/optional/format.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "1990-02-31T15:59:60.123-08:00",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1990-12-31T15:59:60-24:00",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1963-06-19T08:30:06.28123+01:00Z",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "06/19/1963 08:30:06 PST",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "2013-350T01:01:01",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "//foo.bar/?baz=qux#quux",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\fileshare",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "http:// shouldfail.com",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": ":// should fail",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\fileshare",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri-reference"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri-reference"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "#frag\\ment",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri-reference"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri-reference"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "http://example.com/dictionary/{term:1}/{term",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri-template"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri-template"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "2962",
+          "data_pointer": "",
+          "schema": {
+            "format": "email"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "email"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "127.0.0.0.1",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "256.256.256.256",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "127.0",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "0x7f000001",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "12345::",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "::laptop",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "-a-host-name-that-starts-with--",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "not_a_valid_host_name",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "/foo/bar~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "#",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "#/",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "#a",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~0~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~0/~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~2",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~-1",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "0",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a/a",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/oneOf.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ],
+      [
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 2
+          },
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "oneOf"
+        },
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              true,
+              true,
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              true,
+              true,
+              true
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              true,
+              true,
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              true,
+              true,
+              false
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "oneOf": [
+              false,
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "oneOf": [
+              false,
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/oneOf/2",
+          "root_schema": {
+            "oneOf": [
+              false,
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "baz",
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/oneOf/0/properties/bar",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/oneOf/1/properties/foo",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        },
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "baz"
+            ]
+          },
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo",
+              "baz"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2,
+            "baz": 3
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/additionalItems.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/3",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+              }
+            ],
+            "additionalItems": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 4,
+          "data_pointer": "/3",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+              },
+              {
+              },
+              {
+              }
+            ],
+            "additionalItems": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/pattern.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "pattern": "^a*$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "pattern": "^a*$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/definitions.json": [
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/definitions/foo/type",
+          "schema": {
+            "enum": [
+              "array",
+              "boolean",
+              "integer",
+              "null",
+              "number",
+              "object",
+              "string"
+            ]
+          },
+          "schema_pointer": "/definitions/simpleTypes",
+          "root_schema": {
+            "$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": {
+              },
+              "examples": {
+                "type": "array",
+                "items": {
+                }
+              },
+              "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": "#"
+                },
+                "propertyNames": {
+                  "format": "regex"
+                },
+                "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": {
+            }
+          },
+          "type": "enum"
+        },
+        {
+          "data": 1,
+          "data_pointer": "/definitions/foo/type",
+          "schema": {
+            "type": "array",
+            "items": {
+              "$ref": "#/definitions/simpleTypes"
+            },
+            "minItems": 1,
+            "uniqueItems": true
+          },
+          "schema_pointer": "/properties/type/anyOf/1",
+          "root_schema": {
+            "$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": {
+              },
+              "examples": {
+                "type": "array",
+                "items": {
+                }
+              },
+              "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": "#"
+                },
+                "propertyNames": {
+                  "format": "regex"
+                },
+                "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": {
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/maxProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2,
+            "baz": 3
+          },
+          "data_pointer": "",
+          "schema": {
+            "maxProperties": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxProperties": 2
+          },
+          "type": "maxProperties"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/required.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo\nbar": "1",
+            "foo\"bar": "1"
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\nbar",
+              "foo\"bar",
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "required": [
+              "foo\nbar",
+              "foo\"bar",
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          }
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/type.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": "",
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": "",
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/default.json": [
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/multipleOf.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 7,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 2
+          },
+          "type": "multipleOf"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 35,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 1.5
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 1.5
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0.00751,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 0.0001
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 0.0001
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/patternProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": "baz",
+          "data_pointer": "/foooooo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/a",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/a*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": 31,
+          "data_pointer": "/aaaa",
+          "schema": {
+            "maximum": 20
+          },
+          "schema_pointer": "/patternProperties/aaa*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/aaa",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/a*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": 31,
+          "data_pointer": "/aaaa",
+          "schema": {
+            "maximum": 20
+          },
+          "schema_pointer": "/patternProperties/aaa*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "maximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "/a31b",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/patternProperties/[0-9]{2,}",
+          "root_schema": {
+            "patternProperties": {
+              "[0-9]{2,}": {
+                "type": "boolean"
+              },
+              "X_": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "/a_X_3",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/patternProperties/X_",
+          "root_schema": {
+            "patternProperties": {
+              "[0-9]{2,}": {
+                "type": "boolean"
+              },
+              "X_": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/patternProperties/b.*",
+          "root_schema": {
+            "patternProperties": {
+              "f.*": true,
+              "b.*": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/patternProperties/b.*",
+          "root_schema": {
+            "patternProperties": {
+              "f.*": true,
+              "b.*": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/refRemote.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/integer",
+          "root_schema": {
+            "integer": {
+              "type": "integer"
+            },
+            "refToInteger": {
+              "$ref": "#/integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/integer",
+          "root_schema": {
+            "integer": {
+              "type": "integer"
+            },
+            "refToInteger": {
+              "$ref": "#/integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/0/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/list/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/list/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "name": null
+          },
+          "data_pointer": "/name",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "/definitions/orNull/anyOf/0",
+          "root_schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "type": "null"
+        },
+        {
+          "data": {
+            "name": null
+          },
+          "data_pointer": "/name",
+          "schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/allOf.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "baz"
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/allOf/0/properties/bar",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "quux",
+            "baz": null
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2,
+            "baz": null
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": "quux",
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "baz": {
+                "type": "null"
+              }
+            },
+            "required": [
+              "baz"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "baz"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        },
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "baz": {
+                "type": "null"
+              }
+            },
+            "required": [
+              "baz"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "baz"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 35,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 30
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "maximum": 30
+              },
+              {
+                "minimum": 20
+              }
+            ]
+          },
+          "type": "maximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              true,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              {
+              },
+              {
+                "type": "number"
+              }
+            ]
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "type": "number"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/format.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/ref.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "$ref": "#"
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "/foo/bar",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "$ref": "#"
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "$ref": "#/properties/foo"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items/0",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "$ref": "#/items/0"
+              }
+            ]
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/slash",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/slash~1field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/tilda",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/tilda~0field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/percent",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/percent%25field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/a",
+          "root_schema": {
+            "definitions": {
+              "a": {
+                "type": "integer"
+              },
+              "b": {
+                "$ref": "#/definitions/a"
+              },
+              "c": {
+                "$ref": "#/definitions/b"
+              }
+            },
+            "$ref": "#/definitions/c"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "string",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "/definitions/reffed",
+          "root_schema": {
+            "definitions": {
+              "reffed": {
+                "type": "array"
+              }
+            },
+            "properties": {
+              "foo": {
+                "$ref": "#/definitions/reffed",
+                "maxItems": 2
+              }
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": -1,
+          "data_pointer": "/minLength",
+          "schema": {
+            "type": "integer",
+            "minimum": 0
+          },
+          "schema_pointer": "/definitions/nonNegativeInteger",
+          "root_schema": {
+            "$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": {
+              },
+              "examples": {
+                "type": "array",
+                "items": {
+                }
+              },
+              "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": "#"
+                },
+                "propertyNames": {
+                  "format": "regex"
+                },
+                "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": {
+            }
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/$ref",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/$ref",
+          "root_schema": {
+            "properties": {
+              "$ref": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/definitions/bool",
+          "root_schema": {
+            "$ref": "#/definitions/bool",
+            "definitions": {
+              "bool": false
+            }
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "string is invalid",
+          "data_pointer": "/nodes/0/subtree/nodes/0/value",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/definitions/node/properties/value",
+          "root_schema": {
+            "$id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+              "meta": {
+                "type": "string"
+              },
+              "nodes": {
+                "type": "array",
+                "items": {
+                  "$ref": "node"
+                }
+              }
+            },
+            "required": [
+              "meta",
+              "nodes"
+            ],
+            "definitions": {
+              "node": {
+                "$id": "http://localhost:1234/node",
+                "description": "node",
+                "type": "object",
+                "properties": {
+                  "value": {
+                    "type": "number"
+                  },
+                  "subtree": {
+                    "$ref": "tree"
+                  }
+                },
+                "required": [
+                  "value"
+                ]
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/foo\"bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/definitions/foo%22bar",
+          "root_schema": {
+            "properties": {
+              "foo\"bar": {
+                "$ref": "#/definitions/foo%22bar"
+              }
+            },
+            "definitions": {
+              "foo\"bar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "$id": "#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A",
+          "root_schema": {
+            "allOf": [
+              {
+                "$ref": "#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "$id": "#foo",
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "$id": "http://localhost:1234/bar#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A",
+          "root_schema": {
+            "allOf": [
+              {
+                "$ref": "http://localhost:1234/bar#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "$id": "http://localhost:1234/bar#foo",
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "$id": "#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A/definitions/B",
+          "root_schema": {
+            "$id": "http://localhost:1234/root",
+            "allOf": [
+              {
+                "$ref": "http://localhost:1234/nested.json#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "$id": "nested.json",
+                "definitions": {
+                  "B": {
+                    "$id": "#foo",
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/maximum.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3.5,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maximum": 3.0
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/minLength.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "f",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minLength": 2
+          },
+          "type": "minLength"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "💩",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minLength": 2
+          },
+          "type": "minLength"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/maxItems.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3
+          ],
+          "data_pointer": "",
+          "schema": {
+            "maxItems": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxItems": 2
+          },
+          "type": "maxItems"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft6/contains.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "type": "contains"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "type": "contains"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": {
+              "const": 5
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": {
+              "const": 5
+            }
+          },
+          "type": "contains"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": true
+          },
+          "type": "contains"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": [
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": false
+          },
+          "type": "contains"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": false
+          },
+          "type": "contains"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ]
+}
diff --git a/test/fixtures/draft7.json b/test/fixtures/draft7.json
new file mode 100644
index 0000000..40c7404
--- /dev/null
+++ b/test/fixtures/draft7.json
@@ -0,0 +1,9940 @@
+{
+  "JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            1.0,
+            1.0,
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": "bar"
+            },
+            {
+              "foo": "bar"
+            }
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": {
+                "bar": {
+                  "baz": true
+                }
+              }
+            },
+            {
+              "foo": {
+                "bar": {
+                  "baz": true
+                }
+              }
+            }
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            [
+              "foo"
+            ],
+            [
+              "foo"
+            ]
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+            },
+            [
+              1
+            ],
+            true,
+            null,
+            {
+            },
+            1
+          ],
+          "data_pointer": "",
+          "schema": {
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            false
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            true
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            true,
+            "foo",
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            false,
+            "foo",
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true
+          },
+          "type": "uniqueItems"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            false,
+            false
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": [
+            true,
+            true
+          ],
+          "data_pointer": "",
+          "schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "uniqueItems"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "/2",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "boolean"
+              }
+            ],
+            "uniqueItems": true,
+            "additionalItems": false
+          },
+          "type": "schema"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/minItems.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "minItems": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minItems": 1
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "boom",
+          "data_pointer": "/quux",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "patternProperties": {
+              "^v": {
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/élmény",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "patternProperties": {
+              "^á": {
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 12,
+          "data_pointer": "/quux",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                  }
+                }
+              }
+            ],
+            "additionalProperties": {
+              "type": "boolean"
+            }
+          },
+          "type": "boolean"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/dependencies.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": [
+                "foo"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "quux": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 1,
+            "quux": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "quux": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/quux",
+          "root_schema": {
+            "dependencies": {
+              "quux": [
+                "foo",
+                "bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo",
+              "bar"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/foo",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/foo",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/dependencies/bar/properties/bar",
+          "root_schema": {
+            "dependencies": {
+              "bar": {
+                "properties": {
+                  "foo": {
+                    "type": "integer"
+                  },
+                  "bar": {
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/dependencies/bar",
+          "root_schema": {
+            "dependencies": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo\nbar": 1,
+            "foo": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\rbar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo\nbar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\rbar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo\tbar": 1,
+            "a": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "minProperties": 4
+          },
+          "schema_pointer": "/dependencies/foo\tbar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "minProperties"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo'bar": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\"bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo'bar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\"bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo\"bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo'bar"
+            ]
+          },
+          "schema_pointer": "/dependencies/foo\"bar",
+          "root_schema": {
+            "dependencies": {
+              "foo\nbar": [
+                "foo\rbar"
+              ],
+              "foo\tbar": {
+                "minProperties": 4
+              },
+              "foo'bar": {
+                "required": [
+                  "foo\"bar"
+                ]
+              },
+              "foo\"bar": [
+                "foo'bar"
+              ]
+            }
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo'bar"
+            ]
+          }
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "type": "exclusiveMinimum"
+        }
+      ],
+      [
+        {
+          "data": 0.6,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMinimum": 1.1
+          },
+          "type": "exclusiveMinimum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/const.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 5,
+          "data_pointer": "",
+          "schema": {
+            "const": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 2
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "const": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 2
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": [
+            1,
+            2
+          ],
+          "data_pointer": "",
+          "schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": {
+              "foo": "bar",
+              "baz": "bax"
+            }
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            2
+          ],
+          "data_pointer": "",
+          "schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3
+          ],
+          "data_pointer": "",
+          "schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": [
+              {
+                "foo": "bar"
+              }
+            ]
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "const": null
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": null
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "const": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": false
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": 0.0,
+          "data_pointer": "",
+          "schema": {
+            "const": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": false
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "const": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": true
+          },
+          "type": "const"
+        }
+      ],
+      [
+        {
+          "data": 1.0,
+          "data_pointer": "",
+          "schema": {
+            "const": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": true
+          },
+          "type": "const"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "const": 0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 0
+          },
+          "type": "const"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "const": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "const": 1
+          },
+          "type": "const"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/anyOf.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 2
+          },
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 2
+          },
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "maxLength"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 4
+          },
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "type": "string",
+            "anyOf": [
+              {
+                "maxLength": 2
+              },
+              {
+                "minLength": 4
+              }
+            ]
+          },
+          "type": "minLength"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/anyOf/1",
+          "root_schema": {
+            "anyOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/anyOf/0/properties/bar",
+          "root_schema": {
+            "anyOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/anyOf/1/properties/foo",
+          "root_schema": {
+            "anyOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "/anyOf/0/anyOf/0",
+          "root_schema": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            ]
+          },
+          "type": "null"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/propertyNames.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foobar",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 3
+          },
+          "schema_pointer": "/propertyNames",
+          "root_schema": {
+            "propertyNames": {
+              "maxLength": 3
+            }
+          },
+          "type": "maxLength"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/propertyNames",
+          "root_schema": {
+            "propertyNames": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": [
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "",
+          "root_schema": false,
+          "type": "schema"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/not.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": "integer"
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "boolean"
+            ]
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": [
+                "integer",
+                "boolean"
+              ]
+            }
+          },
+          "type": "not"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "boolean"
+            ]
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": [
+                "integer",
+                "boolean"
+              ]
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "bar"
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            }
+          },
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": {
+              "type": "object",
+              "properties": {
+                "foo": {
+                  "type": "string"
+                }
+              }
+            }
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/foo",
+          "schema": {
+          },
+          "schema_pointer": "/properties/foo/not",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "not": {
+                }
+              }
+            }
+          },
+          "type": "not"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": true,
+          "schema_pointer": "/not",
+          "root_schema": {
+            "not": true
+          },
+          "type": "not"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/items.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "x",
+          "data_pointer": "/1",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items/0",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1,
+          "data_pointer": "/1",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/items/1",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/0",
+          "schema": false,
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": false
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": false,
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": false
+          },
+          "type": "schema"
+        },
+        {
+          "data": true,
+          "data_pointer": "/2",
+          "schema": false,
+          "schema_pointer": "/items",
+          "root_schema": {
+            "items": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": false,
+          "schema_pointer": "/items/1",
+          "root_schema": {
+            "items": [
+              true,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            {
+              "foo": null
+            },
+            {
+              "foo": null
+            }
+          ],
+          "data_pointer": "/3",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": null
+          },
+          "data_pointer": "/0/2",
+          "schema": false,
+          "schema_pointer": "/definitions/item/additionalItems",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": null
+          },
+          "data_pointer": "/0",
+          "schema": {
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/sub-item"
+              },
+              {
+                "$ref": "#/definitions/sub-item"
+              }
+            ]
+          },
+          "schema_pointer": "/definitions/item",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "/0/0",
+          "schema": {
+            "type": "object",
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/definitions/sub-item",
+          "root_schema": {
+            "definitions": {
+              "item": {
+                "type": "array",
+                "additionalItems": false,
+                "items": [
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  },
+                  {
+                    "$ref": "#/definitions/sub-item"
+                  }
+                ]
+              },
+              "sub-item": {
+                "type": "object",
+                "required": [
+                  "foo"
+                ]
+              }
+            },
+            "type": "array",
+            "additionalItems": false,
+            "items": [
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              },
+              {
+                "$ref": "#/definitions/item"
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/0/0/0/0",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/items/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "/0/0/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/0/1/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 3,
+          "data_pointer": "/0/2/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 4,
+          "data_pointer": "/1/0/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 5,
+          "data_pointer": "/1/1/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        },
+        {
+          "data": 6,
+          "data_pointer": "/1/2/0",
+          "schema": {
+            "type": "array",
+            "items": {
+              "type": "number"
+            }
+          },
+          "schema_pointer": "/items/items/items",
+          "root_schema": {
+            "type": "array",
+            "items": {
+              "type": "array",
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "array",
+                  "items": {
+                    "type": "number"
+                  }
+                }
+              }
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/enum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 4,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              1,
+              2,
+              3
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              1,
+              2,
+              3
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": false
+          },
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              6,
+              "foo",
+              [
+
+              ],
+              true,
+              {
+                "foo": 12
+              }
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "foo"
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "properties": {
+              "foo": {
+                "enum": [
+                  "foo"
+                ]
+              },
+              "bar": {
+                "enum": [
+                  "bar"
+                ]
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              "foo\nbar",
+              "foo\rbar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              "foo\nbar",
+              "foo\rbar"
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              false
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": 0.0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              false
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              true
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+        {
+          "data": 1.0,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              true
+            ]
+          },
+          "type": "enum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              0
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              0
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "enum": [
+              1
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "enum": [
+              1
+            ]
+          },
+          "type": "enum"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/minProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "minProperties": 1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minProperties": 1
+          },
+          "type": "minProperties"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/properties.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": {
+          },
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "array",
+            "maxItems": 3
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "maxItems"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/foo",
+          "schema": {
+            "minItems": 2
+          },
+          "schema_pointer": "/patternProperties/f.o",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "/fxo",
+          "schema": {
+            "minItems": 2
+          },
+          "schema_pointer": "/patternProperties/f.o",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "minItems"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/quux",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "array",
+                "maxItems": 3
+              },
+              "bar": {
+                "type": "array"
+              }
+            },
+            "patternProperties": {
+              "f.o": {
+                "minItems": 2
+              }
+            },
+            "additionalProperties": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/properties/bar",
+          "root_schema": {
+            "properties": {
+              "foo": true,
+              "bar": false
+            }
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/foo\nbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\nbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\"bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\"bar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\\bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\\bar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\rbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\rbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\tbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\tbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        },
+        {
+          "data": "1",
+          "data_pointer": "/foo\fbar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/properties/foo\fbar",
+          "root_schema": {
+            "properties": {
+              "foo\nbar": {
+                "type": "number"
+              },
+              "foo\"bar": {
+                "type": "number"
+              },
+              "foo\\bar": {
+                "type": "number"
+              },
+              "foo\rbar": {
+                "type": "number"
+              },
+              "foo\tbar": {
+                "type": "number"
+              },
+              "foo\fbar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/maxLength.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "maxLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxLength": 2
+          },
+          "type": "maxLength"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 3.0,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "type": "exclusiveMaximum"
+        }
+      ],
+      [
+        {
+          "data": 3.5,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMaximum": 3.0
+          },
+          "type": "exclusiveMaximum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/minimum.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 0.6,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 1.1
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": 1.1
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": -3,
+          "data_pointer": "",
+          "schema": {
+            "minimum": -2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minimum": -2
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/content.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "{:}",
+          "data_pointer": "",
+          "schema": {
+            "contentMediaType": "application/json"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contentMediaType": "application/json"
+          },
+          "type": "contentMediaType"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "eyJmb28iOi%iYmFyIn0K",
+          "data_pointer": "",
+          "schema": {
+            "contentEncoding": "base64"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contentEncoding": "base64"
+          },
+          "type": "contentEncoding"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "ezp9Cg==",
+          "data_pointer": "",
+          "schema": {
+            "contentMediaType": "application/json",
+            "contentEncoding": "base64"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contentMediaType": "application/json",
+            "contentEncoding": "base64"
+          },
+          "type": "contentMediaType"
+        }
+      ],
+      [
+        {
+          "data": "{}",
+          "data_pointer": "",
+          "schema": {
+            "contentMediaType": "application/json",
+            "contentEncoding": "base64"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contentMediaType": "application/json",
+            "contentEncoding": "base64"
+          },
+          "type": "contentEncoding"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/zeroTerminatedFloats.json": [
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json": [
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 98249283749234923498293171823948729348710298301928331,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 9.727837981879871e+26,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMaximum": 9.727837981879871e+26
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMaximum": 9.727837981879871e+26
+          },
+          "type": "exclusiveMaximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": -9.727837981879871e+26,
+          "data_pointer": "",
+          "schema": {
+            "exclusiveMinimum": -9.727837981879871e+26
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "exclusiveMinimum": -9.727837981879871e+26
+          },
+          "type": "exclusiveMinimum"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "06/19/1963",
+          "data_pointer": "",
+          "schema": {
+            "format": "date"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "2013-350",
+          "data_pointer": "",
+          "schema": {
+            "format": "date"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "/foo/bar~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "#",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "#/",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "#a",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~0~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~0/~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~2",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~-1",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/~~",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "0",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a/a",
+          "data_pointer": "",
+          "schema": {
+            "format": "json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "json-pointer"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "〮실례.테스트",
+          "data_pointer": "",
+          "schema": {
+            "format": "idn-hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "idn-hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "실〮례.테스트",
+          "data_pointer": "",
+          "schema": {
+            "format": "idn-hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "idn-hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트",
+          "data_pointer": "",
+          "schema": {
+            "format": "idn-hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "idn-hostname"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "//foo.bar/?baz=qux#quux",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\fileshare",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "http:// shouldfail.com",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": ":// should fail",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "http://example.com/dictionary/{term:1}/{term",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri-template"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri-template"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\filëßåré",
+          "data_pointer": "",
+          "schema": {
+            "format": "iri-reference"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "iri-reference"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "#ƒräg\\mênt",
+          "data_pointer": "",
+          "schema": {
+            "format": "iri-reference"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "iri-reference"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+          "data_pointer": "",
+          "schema": {
+            "format": "iri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "iri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "/abc",
+          "data_pointer": "",
+          "schema": {
+            "format": "iri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "iri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\filëßåré",
+          "data_pointer": "",
+          "schema": {
+            "format": "iri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "iri"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "âππ",
+          "data_pointer": "",
+          "schema": {
+            "format": "iri"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "iri"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "127.0.0.0.1",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "256.256.256.256",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "127.0",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "0x7f000001",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv4"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv4"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "\\\\WINDOWS\\fileshare",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri-reference"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri-reference"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "#frag\\ment",
+          "data_pointer": "",
+          "schema": {
+            "format": "uri-reference"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "uri-reference"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "08:30:06 PST",
+          "data_pointer": "",
+          "schema": {
+            "format": "time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "01:01:01,1111",
+          "data_pointer": "",
+          "schema": {
+            "format": "time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "time"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "12345::",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "::laptop",
+          "data_pointer": "",
+          "schema": {
+            "format": "ipv6"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "ipv6"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "-a-host-name-that-starts-with--",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "not_a_valid_host_name",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+          "data_pointer": "",
+          "schema": {
+            "format": "hostname"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "hostname"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "2962",
+          "data_pointer": "",
+          "schema": {
+            "format": "email"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "email"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "/foo/bar",
+          "data_pointer": "",
+          "schema": {
+            "format": "relative-json-pointer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "relative-json-pointer"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "1990-02-31T15:59:60.123-08:00",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "1990-12-31T15:59:60-24:00",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+        {
+          "data": "06/19/1963 08:30:06 PST",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "2013-350T01:01:01",
+          "data_pointer": "",
+          "schema": {
+            "format": "date-time"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "date-time"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "^(abc]",
+          "data_pointer": "",
+          "schema": {
+            "format": "regex"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "regex"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "2962",
+          "data_pointer": "",
+          "schema": {
+            "format": "idn-email"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "idn-email"
+          },
+          "type": "format"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json": [
+    [
+      [
+        {
+          "data": "^\\S(|(.|\\n)*\\S)\\Z",
+          "data_pointer": "",
+          "schema": {
+            "format": "regex"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "format": "regex"
+          },
+          "type": "format"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "abc\n",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^abc$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^abc$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\a",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\a$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\cC",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\cC$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "\\cc",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\cc$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "߀",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+        {
+          "data": "߀",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\d$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "0",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\D$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "é",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\w$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\W$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": " ",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\s$"
+          },
+          "type": "pattern"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": " ",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "pattern": "^\\S$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/oneOf.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ],
+      [
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 1.5,
+          "data_pointer": "",
+          "schema": {
+            "minimum": 2
+          },
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "minimum": 2
+              }
+            ]
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "oneOf"
+        },
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string",
+            "oneOf": [
+              {
+                "minLength": 2
+              },
+              {
+                "maxLength": 4
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              true,
+              true,
+              true
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              true,
+              true,
+              true
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              true,
+              true,
+              false
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              true,
+              true,
+              false
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "oneOf": [
+              false,
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "oneOf": [
+              false,
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/oneOf/2",
+          "root_schema": {
+            "oneOf": [
+              false,
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "baz",
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/oneOf/0/properties/bar",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        },
+        {
+          "data": 2,
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/oneOf/1/properties/foo",
+          "root_schema": {
+            "oneOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "oneOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "oneOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "bar"
+            ]
+          },
+          "schema_pointer": "/oneOf/0",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        },
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo",
+              "baz"
+            ]
+          },
+          "schema_pointer": "/oneOf/1",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo",
+              "baz"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2,
+            "baz": 3
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object",
+            "oneOf": [
+              {
+                "required": [
+                  "foo",
+                  "bar"
+                ]
+              },
+              {
+                "required": [
+                  "foo",
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "oneOf"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/if-then-else.json": [
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": -100,
+          "data_pointer": "",
+          "schema": {
+            "minimum": -10
+          },
+          "schema_pointer": "/then",
+          "root_schema": {
+            "if": {
+              "exclusiveMaximum": 0
+            },
+            "then": {
+              "minimum": -10
+            }
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 2
+          },
+          "schema_pointer": "/else",
+          "root_schema": {
+            "if": {
+              "exclusiveMaximum": 0
+            },
+            "else": {
+              "multipleOf": 2
+            }
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": -100,
+          "data_pointer": "",
+          "schema": {
+            "minimum": -10
+          },
+          "schema_pointer": "/then",
+          "root_schema": {
+            "if": {
+              "exclusiveMaximum": 0
+            },
+            "then": {
+              "minimum": -10
+            },
+            "else": {
+              "multipleOf": 2
+            }
+          },
+          "type": "minimum"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 2
+          },
+          "schema_pointer": "/else",
+          "root_schema": {
+            "if": {
+              "exclusiveMaximum": 0
+            },
+            "then": {
+              "minimum": -10
+            },
+            "else": {
+              "multipleOf": 2
+            }
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/additionalItems.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/3",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+              }
+            ],
+            "additionalItems": {
+              "type": "integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 4,
+          "data_pointer": "/3",
+          "schema": false,
+          "schema_pointer": "/additionalItems",
+          "root_schema": {
+            "items": [
+              {
+              },
+              {
+              },
+              {
+              }
+            ],
+            "additionalItems": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/pattern.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "abc",
+          "data_pointer": "",
+          "schema": {
+            "pattern": "^a*$"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "pattern": "^a*$"
+          },
+          "type": "pattern"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/definitions.json": [
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "/definitions/foo/type",
+          "schema": {
+            "enum": [
+              "array",
+              "boolean",
+              "integer",
+              "null",
+              "number",
+              "object",
+              "string"
+            ]
+          },
+          "schema_pointer": "/definitions/simpleTypes",
+          "root_schema": {
+            "$schema": "http://json-schema.org/draft-07/schema#",
+            "$id": "http://json-schema.org/draft-07/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"
+              },
+              "$comment": {
+                "type": "string"
+              },
+              "title": {
+                "type": "string"
+              },
+              "description": {
+                "type": "string"
+              },
+              "default": true,
+              "readOnly": {
+                "type": "boolean",
+                "default": false
+              },
+              "writeOnly": {
+                "type": "boolean",
+                "default": false
+              },
+              "examples": {
+                "type": "array",
+                "items": true
+              },
+              "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": true
+              },
+              "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": "#"
+                },
+                "propertyNames": {
+                  "format": "regex"
+                },
+                "default": {
+                }
+              },
+              "dependencies": {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "$ref": "#"
+                    },
+                    {
+                      "$ref": "#/definitions/stringArray"
+                    }
+                  ]
+                }
+              },
+              "propertyNames": {
+                "$ref": "#"
+              },
+              "const": true,
+              "enum": {
+                "type": "array",
+                "items": true,
+                "minItems": 1,
+                "uniqueItems": true
+              },
+              "type": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/simpleTypes"
+                  },
+                  {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/simpleTypes"
+                    },
+                    "minItems": 1,
+                    "uniqueItems": true
+                  }
+                ]
+              },
+              "format": {
+                "type": "string"
+              },
+              "contentMediaType": {
+                "type": "string"
+              },
+              "contentEncoding": {
+                "type": "string"
+              },
+              "if": {
+                "$ref": "#"
+              },
+              "then": {
+                "$ref": "#"
+              },
+              "else": {
+                "$ref": "#"
+              },
+              "allOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "anyOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "oneOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "not": {
+                "$ref": "#"
+              }
+            },
+            "default": true
+          },
+          "type": "enum"
+        },
+        {
+          "data": 1,
+          "data_pointer": "/definitions/foo/type",
+          "schema": {
+            "type": "array",
+            "items": {
+              "$ref": "#/definitions/simpleTypes"
+            },
+            "minItems": 1,
+            "uniqueItems": true
+          },
+          "schema_pointer": "/properties/type/anyOf/1",
+          "root_schema": {
+            "$schema": "http://json-schema.org/draft-07/schema#",
+            "$id": "http://json-schema.org/draft-07/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"
+              },
+              "$comment": {
+                "type": "string"
+              },
+              "title": {
+                "type": "string"
+              },
+              "description": {
+                "type": "string"
+              },
+              "default": true,
+              "readOnly": {
+                "type": "boolean",
+                "default": false
+              },
+              "writeOnly": {
+                "type": "boolean",
+                "default": false
+              },
+              "examples": {
+                "type": "array",
+                "items": true
+              },
+              "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": true
+              },
+              "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": "#"
+                },
+                "propertyNames": {
+                  "format": "regex"
+                },
+                "default": {
+                }
+              },
+              "dependencies": {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "$ref": "#"
+                    },
+                    {
+                      "$ref": "#/definitions/stringArray"
+                    }
+                  ]
+                }
+              },
+              "propertyNames": {
+                "$ref": "#"
+              },
+              "const": true,
+              "enum": {
+                "type": "array",
+                "items": true,
+                "minItems": 1,
+                "uniqueItems": true
+              },
+              "type": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/simpleTypes"
+                  },
+                  {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/simpleTypes"
+                    },
+                    "minItems": 1,
+                    "uniqueItems": true
+                  }
+                ]
+              },
+              "format": {
+                "type": "string"
+              },
+              "contentMediaType": {
+                "type": "string"
+              },
+              "contentEncoding": {
+                "type": "string"
+              },
+              "if": {
+                "$ref": "#"
+              },
+              "then": {
+                "$ref": "#"
+              },
+              "else": {
+                "$ref": "#"
+              },
+              "allOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "anyOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "oneOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "not": {
+                "$ref": "#"
+              }
+            },
+            "default": true
+          },
+          "type": "array"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/maxProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": 1,
+            "bar": 2,
+            "baz": 3
+          },
+          "data_pointer": "",
+          "schema": {
+            "maxProperties": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxProperties": 2
+          },
+          "type": "maxProperties"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/required.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "bar": 1
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "properties": {
+              "foo": {
+              },
+              "bar": {
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo\nbar": "1",
+            "foo\"bar": "1"
+          },
+          "data_pointer": "",
+          "schema": {
+            "required": [
+              "foo\nbar",
+              "foo\"bar",
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "required": [
+              "foo\nbar",
+              "foo\"bar",
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo\\bar",
+              "foo\rbar",
+              "foo\tbar",
+              "foo\fbar"
+            ]
+          }
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/type.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "number"
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "object"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "object"
+          },
+          "type": "object"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "array"
+          },
+          "type": "array"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": "",
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "boolean"
+          },
+          "type": "boolean"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": 1,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": 0,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": "",
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "null"
+          },
+          "type": "null"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 1.1,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": {
+          },
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "integer",
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "string"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "string"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 123,
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "type": "type"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": [
+              "array",
+              "object",
+              "null"
+            ]
+          },
+          "type": "type"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/default.json": [
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/multipleOf.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 7,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 2
+          },
+          "type": "multipleOf"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 35,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 1.5
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 1.5
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 0.00751,
+          "data_pointer": "",
+          "schema": {
+            "multipleOf": 0.0001
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "multipleOf": 0.0001
+          },
+          "type": "multipleOf"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/patternProperties.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": "baz",
+          "data_pointer": "/foooooo",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/f.*o",
+          "root_schema": {
+            "patternProperties": {
+              "f.*o": {
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "bar",
+          "data_pointer": "/a",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/a*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": 31,
+          "data_pointer": "/aaaa",
+          "schema": {
+            "maximum": 20
+          },
+          "schema_pointer": "/patternProperties/aaa*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/aaa",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/patternProperties/a*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "integer"
+        },
+        {
+          "data": 31,
+          "data_pointer": "/aaaa",
+          "schema": {
+            "maximum": 20
+          },
+          "schema_pointer": "/patternProperties/aaa*",
+          "root_schema": {
+            "patternProperties": {
+              "a*": {
+                "type": "integer"
+              },
+              "aaa*": {
+                "maximum": 20
+              }
+            }
+          },
+          "type": "maximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": null,
+          "data_pointer": "/a31b",
+          "schema": {
+            "type": "boolean"
+          },
+          "schema_pointer": "/patternProperties/[0-9]{2,}",
+          "root_schema": {
+            "patternProperties": {
+              "[0-9]{2,}": {
+                "type": "boolean"
+              },
+              "X_": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "boolean"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3,
+          "data_pointer": "/a_X_3",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/patternProperties/X_",
+          "root_schema": {
+            "patternProperties": {
+              "[0-9]{2,}": {
+                "type": "boolean"
+              },
+              "X_": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/patternProperties/b.*",
+          "root_schema": {
+            "patternProperties": {
+              "f.*": true,
+              "b.*": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/patternProperties/b.*",
+          "root_schema": {
+            "patternProperties": {
+              "f.*": true,
+              "b.*": false
+            }
+          },
+          "type": "schema"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/refRemote.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/integer",
+          "root_schema": {
+            "integer": {
+              "type": "integer"
+            },
+            "refToInteger": {
+              "$ref": "#/integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/integer",
+          "root_schema": {
+            "integer": {
+              "type": "integer"
+            },
+            "refToInteger": {
+              "$ref": "#/integer"
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/0/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/list/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "/list/0",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "type": "integer"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "name": null
+          },
+          "data_pointer": "/name",
+          "schema": {
+            "type": "null"
+          },
+          "schema_pointer": "/definitions/orNull/anyOf/0",
+          "root_schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "type": "null"
+        },
+        {
+          "data": {
+            "name": null
+          },
+          "data_pointer": "/name",
+          "schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "definitions": {
+              "orNull": {
+                "anyOf": [
+                  {
+                    "type": "null"
+                  },
+                  {
+                    "$ref": "#"
+                  }
+                ]
+              }
+            },
+            "type": "string"
+          },
+          "type": "string"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/allOf.json": [
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "baz"
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": "quux",
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/allOf/0/properties/bar",
+          "root_schema": {
+            "allOf": [
+              {
+                "properties": {
+                  "bar": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "bar"
+                ]
+              },
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              }
+            ]
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": {
+            "foo": "quux",
+            "baz": null
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "bar"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2,
+            "baz": null
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "foo": "quux",
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "baz": {
+                "type": "null"
+              }
+            },
+            "required": [
+              "baz"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "baz"
+            ]
+          }
+        }
+      ],
+      [
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "foo": {
+                "type": "string"
+              }
+            },
+            "required": [
+              "foo"
+            ]
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "foo"
+            ]
+          }
+        },
+        {
+          "data": {
+            "bar": 2
+          },
+          "data_pointer": "",
+          "schema": {
+            "properties": {
+              "baz": {
+                "type": "null"
+              }
+            },
+            "required": [
+              "baz"
+            ]
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "properties": {
+              "bar": {
+                "type": "integer"
+              }
+            },
+            "required": [
+              "bar"
+            ],
+            "allOf": [
+              {
+                "properties": {
+                  "foo": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "foo"
+                ]
+              },
+              {
+                "properties": {
+                  "baz": {
+                    "type": "null"
+                  }
+                },
+                "required": [
+                  "baz"
+                ]
+              }
+            ]
+          },
+          "type": "required",
+          "details": {
+            "missing_keys": [
+              "baz"
+            ]
+          }
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 35,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 30
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "maximum": 30
+              },
+              {
+                "minimum": 20
+              }
+            ]
+          },
+          "type": "maximum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              true,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        },
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              false,
+              false
+            ]
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/allOf/1",
+          "root_schema": {
+            "allOf": [
+              {
+              },
+              {
+                "type": "number"
+              }
+            ]
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/allOf/0",
+          "root_schema": {
+            "allOf": [
+              {
+                "type": "number"
+              },
+              {
+              }
+            ]
+          },
+          "type": "number"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/format.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/ref.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "/bar",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "$ref": "#"
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ],
+      [
+        {
+          "data": false,
+          "data_pointer": "/foo/bar",
+          "schema": false,
+          "schema_pointer": "/additionalProperties",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "$ref": "#"
+              }
+            },
+            "additionalProperties": false
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": true,
+          "data_pointer": "/bar",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/properties/foo",
+          "root_schema": {
+            "properties": {
+              "foo": {
+                "type": "integer"
+              },
+              "bar": {
+                "$ref": "#/properties/foo"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "foo",
+          "data_pointer": "/1",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/items/0",
+          "root_schema": {
+            "items": [
+              {
+                "type": "integer"
+              },
+              {
+                "$ref": "#/items/0"
+              }
+            ]
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/slash",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/slash~1field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/tilda",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/tilda~0field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+        {
+          "data": "aoeu",
+          "data_pointer": "/percent",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/percent%25field",
+          "root_schema": {
+            "tilda~field": {
+              "type": "integer"
+            },
+            "slash/field": {
+              "type": "integer"
+            },
+            "percent%field": {
+              "type": "integer"
+            },
+            "properties": {
+              "tilda": {
+                "$ref": "#/tilda~0field"
+              },
+              "slash": {
+                "$ref": "#/slash~1field"
+              },
+              "percent": {
+                "$ref": "#/percent%25field"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/a",
+          "root_schema": {
+            "definitions": {
+              "a": {
+                "type": "integer"
+              },
+              "b": {
+                "$ref": "#/definitions/a"
+              },
+              "c": {
+                "$ref": "#/definitions/b"
+              }
+            },
+            "$ref": "#/definitions/c"
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "string",
+          "data_pointer": "/foo",
+          "schema": {
+            "type": "array"
+          },
+          "schema_pointer": "/definitions/reffed",
+          "root_schema": {
+            "definitions": {
+              "reffed": {
+                "type": "array"
+              }
+            },
+            "properties": {
+              "foo": {
+                "$ref": "#/definitions/reffed",
+                "maxItems": 2
+              }
+            }
+          },
+          "type": "array"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": -1,
+          "data_pointer": "/minLength",
+          "schema": {
+            "type": "integer",
+            "minimum": 0
+          },
+          "schema_pointer": "/definitions/nonNegativeInteger",
+          "root_schema": {
+            "$schema": "http://json-schema.org/draft-07/schema#",
+            "$id": "http://json-schema.org/draft-07/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"
+              },
+              "$comment": {
+                "type": "string"
+              },
+              "title": {
+                "type": "string"
+              },
+              "description": {
+                "type": "string"
+              },
+              "default": true,
+              "readOnly": {
+                "type": "boolean",
+                "default": false
+              },
+              "writeOnly": {
+                "type": "boolean",
+                "default": false
+              },
+              "examples": {
+                "type": "array",
+                "items": true
+              },
+              "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": true
+              },
+              "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": "#"
+                },
+                "propertyNames": {
+                  "format": "regex"
+                },
+                "default": {
+                }
+              },
+              "dependencies": {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "$ref": "#"
+                    },
+                    {
+                      "$ref": "#/definitions/stringArray"
+                    }
+                  ]
+                }
+              },
+              "propertyNames": {
+                "$ref": "#"
+              },
+              "const": true,
+              "enum": {
+                "type": "array",
+                "items": true,
+                "minItems": 1,
+                "uniqueItems": true
+              },
+              "type": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/simpleTypes"
+                  },
+                  {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/simpleTypes"
+                    },
+                    "minItems": 1,
+                    "uniqueItems": true
+                  }
+                ]
+              },
+              "format": {
+                "type": "string"
+              },
+              "contentMediaType": {
+                "type": "string"
+              },
+              "contentEncoding": {
+                "type": "string"
+              },
+              "if": {
+                "$ref": "#"
+              },
+              "then": {
+                "$ref": "#"
+              },
+              "else": {
+                "$ref": "#"
+              },
+              "allOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "anyOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "oneOf": {
+                "$ref": "#/definitions/schemaArray"
+              },
+              "not": {
+                "$ref": "#"
+              }
+            },
+            "default": true
+          },
+          "type": "minimum"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": 2,
+          "data_pointer": "/$ref",
+          "schema": {
+            "type": "string"
+          },
+          "schema_pointer": "/properties/$ref",
+          "root_schema": {
+            "properties": {
+              "$ref": {
+                "type": "string"
+              }
+            }
+          },
+          "type": "string"
+        }
+      ]
+    ],
+    [
+      [
+
+      ]
+    ],
+    [
+      [
+        {
+          "data": "foo",
+          "data_pointer": "",
+          "schema": false,
+          "schema_pointer": "/definitions/bool",
+          "root_schema": {
+            "$ref": "#/definitions/bool",
+            "definitions": {
+              "bool": false
+            }
+          },
+          "type": "schema"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "string is invalid",
+          "data_pointer": "/nodes/0/subtree/nodes/0/value",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/definitions/node/properties/value",
+          "root_schema": {
+            "$id": "http://localhost:1234/tree",
+            "description": "tree of nodes",
+            "type": "object",
+            "properties": {
+              "meta": {
+                "type": "string"
+              },
+              "nodes": {
+                "type": "array",
+                "items": {
+                  "$ref": "node"
+                }
+              }
+            },
+            "required": [
+              "meta",
+              "nodes"
+            ],
+            "definitions": {
+              "node": {
+                "$id": "http://localhost:1234/node",
+                "description": "node",
+                "type": "object",
+                "properties": {
+                  "value": {
+                    "type": "number"
+                  },
+                  "subtree": {
+                    "$ref": "tree"
+                  }
+                },
+                "required": [
+                  "value"
+                ]
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "1",
+          "data_pointer": "/foo\"bar",
+          "schema": {
+            "type": "number"
+          },
+          "schema_pointer": "/definitions/foo%22bar",
+          "root_schema": {
+            "properties": {
+              "foo\"bar": {
+                "$ref": "#/definitions/foo%22bar"
+              }
+            },
+            "definitions": {
+              "foo\"bar": {
+                "type": "number"
+              }
+            }
+          },
+          "type": "number"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "$id": "#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A",
+          "root_schema": {
+            "allOf": [
+              {
+                "$ref": "#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "$id": "#foo",
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "$id": "http://localhost:1234/bar#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A",
+          "root_schema": {
+            "allOf": [
+              {
+                "$ref": "http://localhost:1234/bar#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "$id": "http://localhost:1234/bar#foo",
+                "type": "integer"
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": "a",
+          "data_pointer": "",
+          "schema": {
+            "$id": "#foo",
+            "type": "integer"
+          },
+          "schema_pointer": "/definitions/A/definitions/B",
+          "root_schema": {
+            "$id": "http://localhost:1234/root",
+            "allOf": [
+              {
+                "$ref": "http://localhost:1234/nested.json#foo"
+              }
+            ],
+            "definitions": {
+              "A": {
+                "$id": "nested.json",
+                "definitions": {
+                  "B": {
+                    "$id": "#foo",
+                    "type": "integer"
+                  }
+                }
+              }
+            }
+          },
+          "type": "integer"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/maximum.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": 3.5,
+          "data_pointer": "",
+          "schema": {
+            "maximum": 3.0
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maximum": 3.0
+          },
+          "type": "maximum"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/minLength.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "f",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minLength": 2
+          },
+          "type": "minLength"
+        }
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": "💩",
+          "data_pointer": "",
+          "schema": {
+            "minLength": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "minLength": 2
+          },
+          "type": "minLength"
+        }
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/maxItems.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3
+          ],
+          "data_pointer": "",
+          "schema": {
+            "maxItems": 2
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "maxItems": 2
+          },
+          "type": "maxItems"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ],
+  "JSON-Schema-Test-Suite/tests/draft7/contains.json": [
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "type": "contains"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": {
+              "minimum": 5
+            }
+          },
+          "type": "contains"
+        }
+      ],
+      [
+
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+
+      ],
+      [
+        {
+          "data": [
+            1,
+            2,
+            3,
+            4
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": {
+              "const": 5
+            }
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": {
+              "const": 5
+            }
+          },
+          "type": "contains"
+        }
+      ]
+    ],
+    [
+      [
+
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": true
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": true
+          },
+          "type": "contains"
+        }
+      ]
+    ],
+    [
+      [
+        {
+          "data": [
+            "foo"
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": false
+          },
+          "type": "contains"
+        }
+      ],
+      [
+        {
+          "data": [
+
+          ],
+          "data_pointer": "",
+          "schema": {
+            "contains": false
+          },
+          "schema_pointer": "",
+          "root_schema": {
+            "contains": false
+          },
+          "type": "contains"
+        }
+      ],
+      [
+
+      ]
+    ]
+  ]
+}
diff --git a/test/json_schemer_test.rb b/test/json_schemer_test.rb
new file mode 100644
index 0000000..1c814ad
--- /dev/null
+++ b/test/json_schemer_test.rb
@@ -0,0 +1,1176 @@
+require 'test_helper'
+
+class JSONSchemerTest < Minitest::Test
+  def test_that_it_has_a_version_number
+    refute_nil(JSONSchemer::VERSION)
+  end
+
+  def test_it_does_something_useful
+    schema = {
+      'type' => 'object',
+      'maxProperties' => 4,
+      'minProperties' => 1,
+      'required' => [
+        'one'
+      ],
+      'properties' => {
+        'one' => {
+          'type' => 'string',
+          'maxLength' => 5,
+          'minLength' => 3,
+          'pattern' => '\w+'
+        },
+        'two' => {
+          'type' => 'integer',
+          'minimum' => 10,
+          'maximum' => 100,
+          'multipleOf' => 5
+        },
+        'three' => {
+          'type' => 'array',
+          'maxItems' => 2,
+          'minItems' => 2,
+          'uniqueItems' => true,
+          'contains' => {
+            'type' => 'integer'
+          }
+        }
+      },
+      'additionalProperties' => {
+        'type' => 'string'
+      },
+      'propertyNames' => {
+        'type' => 'string',
+        'pattern' => '\w+'
+      },
+      'dependencies' => {
+        'one' => [
+          'two'
+        ],
+        'two' => {
+          'minProperties' => 1
+        }
+      }
+    }
+    data = {
+      'one' => 'value',
+      'two' => 100,
+      'three' => [1, 2],
+      '123' => 'x'
+    }
+    schema = JSONSchemer.schema(schema)
+    assert(schema.valid?(data))
+    errors = schema.validate(data)
+    assert(errors.none?)
+  end
+
+  def test_it_inserts_defaults
+    schema = {
+      'required' => ['a', 'c', 'd'],
+      'properties' => {
+        'a' => { 'default' => 1 },
+        'b' => { 'default' => 2 },
+        'c' => {
+          'required' => ['x'],
+          'properties' => {
+            'x' => { 'default' => 3 },
+            'y' => { 'default' => 4 }
+          }
+        },
+        'd' => {
+          'required' => ['x'],
+          'default' => {
+            'x' => {
+              'y' => {
+                'z' => 1
+              }
+            }
+          },
+          'properties' => {
+            'x' => {
+              'required' => ['y'],
+              'properties' => {
+                'y' => {
+                  'required' => ['z'],
+                  'properties' => {
+                    'z' => { 'type' => 'integer' }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    data = {
+      'a' => 10,
+      'c' => {
+        'x' => 30
+      }
+    }
+    refute(JSONSchemer.schema(schema).valid?(data))
+    assert(JSONSchemer.schema(schema, insert_property_defaults: true).valid?(data))
+    assert_equal(
+      {
+        'a' => 10,
+        'b' => 2,
+        'c' => {
+          'x' => 30,
+          'y' => 4
+        },
+        'd' => {
+          'x' => {
+            'y' => {
+              'z' => 1
+            }
+          }
+        }
+      },
+      data
+    )
+  end
+
+  def test_it_does_not_fail_using_insert_defaults_when_no_properties_are_defined_by_schema
+    schema = {
+      '$comment' => 'Mostly empty schema'
+    }
+    data = {
+      'a' => 1
+    }
+    assert(JSONSchemer.schema(schema, insert_property_defaults: true).valid?(data))
+    assert_equal({ 'a' => 1 }, data)
+  end
+
+  def test_it_does_not_fail_using_insert_defaults_when_properties_contains_a_boolean_defined_property
+    schema = {
+      'properties' => {
+        'a' => true
+      }
+    }
+    data = {
+      'a' => 1
+    }
+    assert(JSONSchemer.schema(schema, insert_property_defaults: true).valid?(data))
+    assert_equal({ 'a' => 1 }, data)
+  end
+
+  def test_it_does_not_fail_using_insert_defaults_when_properties_contains_a_boolean_defined_property_that_does_not_exist
+    schema = {
+      'properties' => {
+        'b' => true
+      }
+    }
+    data = {
+      'a' => 1
+    }
+    assert(JSONSchemer.schema(schema, insert_property_defaults: true).valid?(data))
+    assert_equal({ 'a' => 1 }, data)
+  end
+
+  def test_it_does_not_insert_defaults_in_conditional_subschemas
+    subschema = {
+      'properties' => {
+        'a' => {
+          'const' => 1
+        },
+        'b' => {
+          'const' => 2,
+          'default' => 2
+        }
+      }
+    }
+    schema = {
+      'allOf' => [subschema],
+      'anyOf' => [subschema],
+      'oneOf' => [subschema],
+      'if' => subschema
+    }
+    data = {
+      'a' => 1
+    }
+    assert(JSONSchemer.schema(schema, insert_property_defaults: true).valid?(data))
+    assert_equal({ 'a' => 1 }, data)
+    refute(JSONSchemer.schema(schema.merge('not' => subschema), insert_property_defaults: true).valid?(data))
+    assert_equal({ 'a' => 1 }, data)
+  end
+
+  def test_it_calls_before_validation_hooks_to_modify_data
+    parse_array = proc do |data, property, property_schema, _|
+      if data.key?(property) && property_schema.is_a?(Hash) && property_schema['type'] == 'array'
+        parsed = data[property].split(',')
+        parsed = parsed.map!(&:to_i) if property_schema['items']['type'] == 'integer'
+        data[property] = parsed
+      end
+    end
+    data = { 'list' => '1,2,3' }
+    schema = {
+      'properties' => {
+        'list' => {
+          'type' => 'array',
+          'items' => { 'type' => 'integer' }
+        }
+      }
+    }
+    assert(JSONSchemer.schema(
+      schema,
+      before_property_validation: [parse_array]
+    ).valid?(data))
+    assert_equal({'list' => [1, 2, 3]}, data)
+  end
+
+  def test_use_before_validation_hook_to_act_on_parent_schema
+    skip_read_only = proc do |data, property, property_schema, schema|
+      return unless property_schema['readOnly']
+      schema['required'].delete(property) if schema['required']
+      if data.key?(property) && property_schema.is_a?(Hash)
+        data.delete(property)
+      end
+    end
+    schema = {
+      'required' => ['id'],
+      'properties' => {
+        'id' => {
+          'type' => 'integer',
+          'readOnly' => true
+        }
+      }
+    }
+    schemer = JSONSchemer.schema(
+      schema,
+      before_property_validation: [skip_read_only]
+    )
+    data = { 'id' => 1 }
+    assert_empty(schemer.validate(data).to_a)
+    assert_equal({}, data)
+
+    data = {}
+    assert_empty(schemer.validate(data).to_a)
+    assert_equal({}, data)
+  end
+
+  def test_it_accepts_a_single_before_validation_hook_to_modify_data
+    parse_array = proc do |data, property, property_schema, _|
+      if data.key?(property) && property_schema.is_a?(Hash) && property_schema['type'] == 'array'
+        parsed = data[property].split(',')
+        parsed = parsed.map!(&:to_i) if property_schema['items']['type'] == 'integer'
+        data[property] = parsed
+      end
+    end
+    data = { 'list' => '1,2,3' }
+    schema = {
+      'properties' => {
+        'list' => {
+          'type' => 'array',
+          'items' => { 'type' => 'integer' }
+        }
+      }
+    }
+    assert(JSONSchemer.schema(
+      schema,
+      before_property_validation: parse_array
+    ).valid?(data))
+    assert_equal({'list' => [1, 2, 3]}, data)
+  end
+
+  def test_it_calls_before_validation_hooks_and_still_inserts_defaults
+    replace_fake_with_peter = proc do |data, property, property_schema, _|
+      data[property] = 'Peter' if property == 'name' && data[property] == 'fake'
+    end
+    data = [{ }, { 'name' => 'Bob' }]
+    assert(JSONSchemer.schema(
+      {
+        'type' => 'array',
+        'items' => {
+          'type' => 'object',
+          'properties' => {
+            'name' => {
+              'type' => 'string',
+              'default' => 'fake'
+            }
+          }
+        }
+      },
+      insert_property_defaults: true,
+      before_property_validation: [replace_fake_with_peter]
+    ).valid?(data))
+    assert_equal([{ 'name' => 'Peter' }, { 'name' => 'Bob' }], data)
+  end
+
+  def test_it_calls_after_validation_hooks_to_modify_data
+    convert_date = proc do |data, property, property_schema, _|
+      if data[property] && property_schema.is_a?(Hash) && property_schema['format'] == 'date'
+        data[property] = Date.iso8601(data[property])
+      end
+    end
+    schema = {
+      'properties' => {
+        'start_date' => {
+          'type' => 'string',
+          'format' => 'date'
+        }
+      }
+    }
+    validator= JSONSchemer.schema(
+      schema,
+      after_property_validation: [convert_date]
+    )
+    data = { 'start_date' => '2020-09-03' }
+    assert(validator.valid?(data))
+    assert_equal({'start_date' => Date.new(2020, 9, 3)}, data)
+  end
+
+  def test_it_accepts_a_single_proc_as_after_validation_hook
+    convert_date = proc do |data, property, property_schema|
+      if data[property] && property_schema.is_a?(Hash) && property_schema['format'] == 'date'
+        data[property] = Date.iso8601(data[property])
+      end
+    end
+    schema = {
+      'properties' => {
+        'start_date' => {
+          'type' => 'string',
+          'format' => 'date'
+        }
+      }
+    }
+    validator= JSONSchemer.schema(
+      schema,
+      after_property_validation: convert_date
+    )
+    data = { 'start_date' => '2020-09-03' }
+    assert(validator.valid?(data))
+    assert_equal({'start_date' => Date.new(2020, 9, 3)}, data)
+  end
+
+  def test_it_does_not_modify_passed_hooks_array
+    schema = {
+      'properties' => {
+        'list' => {
+          'type' => 'array',
+          'items' => { 'type' => 'string' }
+        }
+      }
+    }
+    data = [{ 'name' => 'Bob' }]
+    assert(JSONSchemer.schema(
+      schema,
+      before_property_validation: [proc {}].freeze,
+      after_property_validation: [proc {}].freeze,
+      insert_property_defaults: true
+    ).valid?(data))
+  end
+
+  def test_it_does_not_fail_when_the_schema_is_completely_empty
+    schema = {}
+    data = {
+      'a' => 1
+    }
+    assert(JSONSchemer.schema(schema).valid?(data))
+    assert_equal({ 'a' => 1 }, data)
+  end
+
+  def test_it_allows_disabling_format
+    schema = JSONSchemer.schema(
+      { 'format' => 'email' },
+      format: false
+    )
+    assert(schema.valid?('not-an-email'))
+  end
+
+  def test_it_ignores_format_for_invalid_type
+    schema = JSONSchemer.schema({
+      'format' => 'email'
+    })
+    refute(schema.valid?('not-an-email'))
+    assert(schema.valid?({}))
+  end
+
+  def test_it_allows_false_custom_format
+    schema = JSONSchemer.schema(
+      {
+        'type' => 'object',
+        'properties' => {
+          'one' => {
+            'format' => 'email'
+          },
+          'two' => {
+            'format' => 'time'
+          }
+        }
+      },
+      formats: {
+        'email' => false
+      }
+    )
+    data = {
+      'one' => 'not-an-email',
+      'two' => 'not-a-time'
+    }
+    errors = schema.validate(data).to_a
+    assert_equal(1, errors.size)
+    assert_equal('not-a-time', errors.first.fetch('data'))
+    assert_equal('format', errors.first.fetch('type'))
+  end
+
+  def test_it_allows_callable_custom_format
+    schema = JSONSchemer.schema(
+      { 'format' => 'custom' },
+      formats: {
+        'custom' => proc { |x| x == 'valid' }
+      }
+    )
+    assert(schema.valid?('valid'))
+    refute(schema.valid?('invalid'))
+  end
+
+  def test_it_returns_correct_pointers_for_ref_pointer
+    ref_schema = { 'type' => 'string' }
+    root = {
+      'definitions' => {
+        'y' => ref_schema
+      },
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => '#/definitions/y' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(root)
+    errors = schema.validate({ 'a' => { 'x' => 1 } }).to_a
+    assert_equal(
+      {
+        'data' => 1,
+        'data_pointer' => '/a/x',
+        'schema' => ref_schema,
+        'schema_pointer' => '/definitions/y',
+        'root_schema' => root,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_it_returns_correct_pointers_for_remote_ref_pointer
+    ref_schema = { 'type' => 'string' }
+    ref = {
+      'definitions' => {
+        'y' => ref_schema
+      }
+    }
+    root = {
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => 'http://example.com/#/definitions/y' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(
+      root,
+      ref_resolver: proc { ref }
+    )
+    errors = schema.validate({ 'a' => { 'x' => 1 } }).to_a
+    assert_equal(
+      {
+        'data' => 1,
+        'data_pointer' => '/a/x',
+        'schema' => ref_schema,
+        'schema_pointer' => '/definitions/y',
+        'root_schema' => ref,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_it_returns_correct_pointers_for_ref_id
+    ref_schema = {
+      '$id' => 'http://example.com/foo',
+      'type' => 'string'
+    }
+    root = {
+      'definitions' => {
+        'y' => ref_schema
+      },
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => 'http://example.com/foo' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(root)
+    errors = schema.validate({ 'a' => { 'x' => 1 } }).to_a
+    assert_equal(
+      {
+        'data' => 1,
+        'data_pointer' => '/a/x',
+        'schema' => ref_schema,
+        'schema_pointer' => '/definitions/y',
+        'root_schema' => root,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_can_refer_to_subschemas_inside_hashes
+    root = {
+     'foo' => {
+        'bar' => {
+          '$id' => '#bar',
+          'type' => 'string'
+        }
+      },
+      '$ref' => '#bar'
+    }
+    schema = JSONSchemer.schema(
+      root
+    )
+    errors = schema.validate(42).to_a
+    assert_equal(
+      {
+        'data' => 42,
+        'data_pointer' => '',
+        'schema' => root['foo']['bar'],
+        'schema_pointer' => '/foo/bar',
+        'root_schema' => root,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_can_refer_to_subschemas_inside_arrays
+    root = {
+     'foo' => [{
+        'bar' => {
+          '$id' => '#bar',
+          'type' => 'string'
+        }
+      }],
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => '#bar' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(root)
+    errors = schema.validate({ 'a' => { 'x' => 1 } }).to_a
+    assert_equal(
+      {
+        'data' => 1,
+        'data_pointer' => '/a/x',
+        'schema' => root['foo'].first['bar'],
+        'schema_pointer' => '/foo/0/bar',
+        'root_schema' => root,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_can_refer_to_subschemas_in_hash_with_remote_pointer
+    ref_schema = {
+      '$id' => 'http://example.com/ref_schema.json',
+      'foo' => {
+        'bar' => {
+          '$id' => '#bar',
+          'type' => 'string'
+        }
+      }
+    }
+    root = {
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => 'http://example.com/ref_schema.json#bar' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(
+      root,
+      ref_resolver: proc { ref_schema }
+    )
+    errors = schema.validate({ 'a' => { 'x' => 1 } }).to_a
+    assert_equal(
+      {
+        'data' => 1,
+        'data_pointer' => '/a/x',
+        'schema' => ref_schema['foo']['bar'],
+        'schema_pointer' => '/foo/bar',
+        'root_schema' => ref_schema,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_can_refer_to_multiple_subschemas_in_hash
+    ref_schema = {
+      '$id' => 'http://example.com/ref_schema.json',
+      'types' => {
+        'uuid' => {
+           '$id' => "#uuid",
+           'type' => 'string',
+           'pattern' => "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
+        }
+      },
+      'foo' => {
+        'bar' => {
+          '$id' => '#bar',
+          'allOf' => [{ "$ref" => "#uuid"}]
+        }
+      }
+    }
+    root = {
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => 'http://example.com/ref_schema.json#bar' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(
+      root,
+      ref_resolver: proc { ref_schema }
+    )
+    errors = schema.validate({ 'a' => { 'x' => "1122-112" } }).to_a
+    assert_equal(
+      {
+        'data' => "1122-112",
+        'data_pointer' => '/a/x',
+        'schema' => ref_schema['types']['uuid'],
+        'schema_pointer' => '/types/uuid',
+        'root_schema' => ref_schema,
+        'type' => 'pattern'
+      },
+      errors.first
+    )
+  end
+
+  def test_it_returns_correct_pointers_for_remote_ref_id
+    ref_schema = {
+      '$id' => 'http://example.com/remote-id',
+      'type' => 'string'
+    }
+    ref = {
+      'definitions' => {
+        'y' => ref_schema
+      }
+    }
+    root = {
+      'properties' => {
+        'a' => {
+          'properties' => {
+            'x' => { '$ref' => 'http://example.com/remote-id' }
+          }
+        }
+      }
+    }
+    schema = JSONSchemer.schema(
+      root,
+      ref_resolver: proc { ref }
+    )
+    errors = schema.validate({ 'a' => { 'x' => 1 } }).to_a
+    assert_equal(
+      {
+        'data' => 1,
+        'data_pointer' => '/a/x',
+        'schema' => ref_schema,
+        'schema_pointer' => '/definitions/y',
+        'root_schema' => ref,
+        'type' => 'string'
+      },
+      errors.first
+    )
+  end
+
+  def test_it_returns_correct_pointers_for_items_array
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'x' => {
+            'items' => [
+              { 'type' => 'integer' },
+              { 'type' => 'string' }
+            ]
+          }
+        }
+      }
+    )
+    errors = schema.validate({ 'x' => ['wrong', 1] }).to_a
+    assert_equal(['/x/0', '/properties/x/items/0'], errors.first.values_at('data_pointer', 'schema_pointer'))
+    assert_equal(['/x/1', '/properties/x/items/1'], errors.last.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_returns_correct_pointers_for_additional_items
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'x' => {
+            'items' => [
+              { 'type' => 'integer' }
+            ],
+            'additionalItems' => { 'type' => 'string' }
+          }
+        }
+      }
+    )
+    errors = schema.validate({ 'x' => ['wrong', 1] }).to_a
+    assert_equal(['/x/0', '/properties/x/items/0'], errors.first.values_at('data_pointer', 'schema_pointer'))
+    assert_equal(['/x/1', '/properties/x/additionalItems'], errors.last.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_returns_correct_pointers_for_items
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'x' => {
+            'items' => { 'type' => 'boolean' }
+          }
+        }
+      }
+    )
+    errors = schema.validate({ 'x' => ['wrong', 1] }).to_a
+    assert_equal(['/x/0', '/properties/x/items'], errors.first.values_at('data_pointer', 'schema_pointer'))
+    assert_equal(['/x/1', '/properties/x/items'], errors.last.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_returns_correct_pointers_for_dependencies
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'a' => {
+            'dependencies' => {
+              'x' => ['y'],
+              'z' => { 'minProperties' => 10 }
+            }
+          }
+        }
+      }
+    )
+    errors = schema.validate({
+      'a' => {
+        'x' => 1,
+        'z' => 2
+      }
+    }).to_a
+    assert_equal(['/a', '/properties/a/dependencies/x'], errors.first.values_at('data_pointer', 'schema_pointer'))
+    assert_equal(['/a', '/properties/a/dependencies/z'], errors.last.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_returns_correct_pointers_for_property_names
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'x' => {
+            'propertyNames' => { 'minLength' => 10 }
+          }
+        }
+      }
+    )
+    errors = schema.validate({ 'x' => { 'abc' => 1 } }).to_a
+    assert_equal(['/x', '/properties/x/propertyNames'], errors.first.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_returns_correct_pointers_for_pattern_properties
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'x' => {
+            'patternProperties' => {
+              '^a' => { 'type' => 'string' }
+            }
+          }
+        }
+      }
+    )
+    errors = schema.validate({ 'x' => { 'abc' => 1 } }).to_a
+    assert_equal(['/x/abc', '/properties/x/patternProperties/^a'], errors.first.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_returns_correct_pointers_for_additional_properties
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'x' => {
+            'additionalProperties' => { 'type' => 'string' }
+          }
+        }
+      }
+    )
+    errors = schema.validate({ 'x' => { 'abc' => 1 } }).to_a
+    assert_equal(['/x/abc', '/properties/x/additionalProperties'], errors.first.values_at('data_pointer', 'schema_pointer'))
+  end
+
+  def test_it_raises_for_invalid_file_uris
+    schemas = Pathname.new(__dir__).join('schemas')
+    assert_raises(JSONSchemer::InvalidFileURI) { JSONSchemer.schema(schemas.join('file_uri_ref_invalid_host.json')).valid?({}) }
+    assert_raises(JSONSchemer::InvalidFileURI) { JSONSchemer.schema(schemas.join('file_uri_ref_invalid_scheme.json')).valid?({}) }
+  end
+
+  def test_it_handles_pathnames
+    schema = JSONSchemer.schema(Pathname.new(__dir__).join('schemas', 'schema1.json'))
+    assert_equal('required', schema.validate({ 'id' => 1 }).first.fetch('type'))
+    assert_equal('required', schema.validate({ 'a' => 'abc' }).first.fetch('type'))
+    assert_equal('string', schema.validate({ 'id' => 1, 'a' => 1 }).first.fetch('type'))
+    assert(schema.valid?({ 'id' => 1, 'a' => 'abc' }))
+  end
+
+  def test_required_validation_adds_missing_keys
+    schema = JSONSchemer.schema(Pathname.new(__dir__).join('schemas', 'schema1.json'))
+    error = schema.validate({ 'id' => 1 }).first
+    assert_equal('required', error.fetch('type'))
+    assert_equal({ 'missing_keys' => ['a'] }, error.fetch('details'))
+  end
+
+  def test_it_allows_custom_ref_resolver_with_pathnames
+    count = 0
+    schema = JSONSchemer.schema(
+      Pathname.new(__dir__).join('schemas', 'schema1.json'),
+      :ref_resolver => proc do |uri|
+        count += 1
+        true
+      end
+    )
+    assert(schema.valid?({ 'id' => 1, 'a' => 'abc' }))
+    assert_equal(2, count)
+  end
+
+  def test_it_raises_for_invalid_ref_resolution
+    schema = JSONSchemer.schema(
+      { '$ref' => 'http://example.com' },
+      :ref_resolver => proc { |uri| nil }
+    )
+    assert_raises(JSONSchemer::InvalidRefResolution) { schema.valid?('value') }
+  end
+
+  def test_it_handles_json_strings
+    schema = JSONSchemer.schema('{ "type": "integer" }')
+    assert(schema.valid?(1))
+    refute(schema.valid?('1'))
+  end
+
+  def test_it_checks_for_symbol_keys
+    assert_raises(JSONSchemer::InvalidSymbolKey) { JSONSchemer.schema({ :type => 'integer' }) }
+    schema = JSONSchemer.schema(
+      { '$ref' => 'http://example.com' },
+      :ref_resolver => proc do |uri|
+        { :type => 'integer' }
+      end
+    )
+    assert_raises(JSONSchemer::InvalidSymbolKey) { schema.valid?(1) }
+  end
+
+  def test_cached_ref_resolver
+    schema = {
+      'properties' => {
+        'x' => { '$ref' => 'http://example.com/1' },
+        'y' => { '$ref' => 'http://example.com/1' },
+        'z' => { '$ref' => 'http://example.com/2' }
+      }
+    }
+    data = { 'x' => '', 'y' => '', 'z' => '' }
+    counts = Hash.new(0)
+    ref_resolver = proc do |uri|
+      counts[uri.to_s] += 1
+      { 'type' => 'string' }
+    end
+    assert(JSONSchemer.schema(schema, :ref_resolver => ref_resolver).valid?(data))
+    assert_equal(2, counts['http://example.com/1'])
+    assert_equal(1, counts['http://example.com/2'])
+    counts.clear
+    assert(JSONSchemer.schema(schema, :ref_resolver => JSONSchemer::CachedRefResolver.new(&ref_resolver)).valid?(data))
+    assert_equal(1, counts['http://example.com/1'])
+    assert_equal(1, counts['http://example.com/2'])
+    counts.clear
+    assert(JSONSchemer.schema(schema, :ref_resolver => JSONSchemer::CachedResolver.new(&ref_resolver)).valid?(data))
+    assert_equal(1, counts['http://example.com/1'])
+    assert_equal(1, counts['http://example.com/2'])
+  end
+
+  def test_it_handles_regex_anchors
+    schema = JSONSchemer.schema({ 'pattern' => '^foo$' })
+    assert(schema.valid?('foo'))
+    refute(schema.valid?(' foo'))
+    refute(schema.valid?('foo '))
+    refute(schema.valid?("foo\nfoo\nfoo"))
+
+    schema = JSONSchemer.schema({ 'pattern' => '\Afoo\z' })
+    assert(schema.valid?('Afooz'))
+    refute(schema.valid?('foo'))
+    refute(schema.valid?('Afoo'))
+    refute(schema.valid?('fooz'))
+  end
+
+  def test_it_handles_regexp_resolver
+    new_regexp_class = Class.new do
+      def self.counts
+        @@counts ||= 0
+      end
+
+      def self.counts=(value)
+        @@counts = value
+      end
+
+      def initialize(pattern)
+        @regexp = Regexp.new(pattern)
+        self.class.counts += 1
+      end
+
+      def match?(string)
+        @regexp.match?(string)
+      end
+    end
+
+    schema = JSONSchemer.schema({ 'pattern' => '^foo$' }, regexp_resolver: -> (pattern) { new_regexp_class.new(pattern) })
+    assert(schema.valid?('foo'))
+    assert_equal(1, new_regexp_class.counts)
+  end
+
+  def test_it_allows_named_regexp_resolvers
+    schema = JSONSchemer.schema({ 'pattern' => '^test$' })
+    assert(schema.valid?("test"))
+    refute(schema.valid?("\ntest\n"))
+    schema = JSONSchemer.schema({ 'pattern' => '^test$' }, :regexp_resolver => 'ecma')
+    assert(schema.valid?("test"))
+    refute(schema.valid?("\ntest\n"))
+    schema = JSONSchemer.schema({ 'pattern' => '^test$' }, :regexp_resolver => 'ruby')
+    assert(schema.valid?("test"))
+    assert(schema.valid?("\ntest\n"))
+  end
+
+  def test_it_raises_for_invalid_regexp_resolution
+    schema = JSONSchemer.schema(
+      { 'pattern' => 'whatever' },
+      :regexp_resolver => proc { |pattern| nil }
+    )
+    assert_raises(JSONSchemer::InvalidRegexpResolution) { schema.valid?('value') }
+  end
+
+  def test_cached_regexp_resolver
+    schema = {
+      'properties' => {
+        'x' => { 'pattern' => '^1$' },
+        'y' => { 'pattern' => '^1$' },
+        'z' => { 'pattern' => '^2$' }
+      }
+    }
+    data = { 'x' => '1', 'y' => '1', 'z' => '2' }
+    counts = Hash.new(0)
+    regexp_resolver = proc do |pattern|
+      counts[pattern] += 1
+      Regexp.new(pattern)
+    end
+    assert(JSONSchemer.schema(schema, :regexp_resolver => regexp_resolver).valid?(data))
+    assert_equal(2, counts['^1$'])
+    assert_equal(1, counts['^2$'])
+    counts.clear
+    assert(JSONSchemer.schema(schema, :regexp_resolver => JSONSchemer::CachedResolver.new(&regexp_resolver)).valid?(data))
+    assert_equal(1, counts['^1$'])
+    assert_equal(1, counts['^2$'])
+  end
+
+  def test_it_returns_nested_errors
+    root = {
+      'type' => 'object',
+      'required' => [
+        'numberOfModules'
+      ],
+      'properties' => {
+        'numberOfModules' => {
+          'allOf' => [
+            {
+              'not' => {
+                'type' => 'integer',
+                'minimum' => 38
+              }
+            },
+            {
+              'not' => {
+                'type' => 'integer',
+                'maximum' => 37,
+                'minimum' => 25
+              }
+            },
+            {
+              'not' => {
+                'type' => 'integer',
+                'maximum' => 24,
+                'minimum' => 12
+              }
+            }
+          ],
+          'anyOf' => [
+            { 'type' => 'integer' },
+            { 'type' => 'string' }
+          ],
+          'oneOf' => [
+            { 'type' => 'integer' },
+            { 'type' => 'integer' },
+            { 'type' => 'boolean' }
+          ]
+        }
+      }
+    }
+    schema = JSONSchemer.schema(root)
+    assert_equal(
+      {
+        'data' => 32,
+        'data_pointer' => '/numberOfModules',
+        'schema' => {
+          'type' => 'integer',
+          'maximum' => 37,
+          'minimum' => 25
+        },
+        'schema_pointer' => '/properties/numberOfModules/allOf/1/not',
+        'root_schema' => root,
+        'type' => 'not'
+      },
+      schema.validate({ 'numberOfModules' => 32 }).first
+    )
+    assert_equal(
+      {
+        'data' => true,
+        'data_pointer' => '/numberOfModules',
+        'schema' => {
+          'type' => 'integer'
+        },
+        'schema_pointer' => '/properties/numberOfModules/anyOf/0',
+        'root_schema' => root,
+        'type' => 'integer'
+      },
+      schema.validate({ 'numberOfModules' => true }).first
+    )
+    assert_equal(
+      {
+        'data' => 8,
+        'data_pointer' => '/numberOfModules',
+        'schema' => root.fetch('properties').fetch('numberOfModules'),
+        'schema_pointer' => '/properties/numberOfModules',
+        'root_schema' => root,
+        'type' => 'oneOf'
+      },
+      schema.validate({ 'numberOfModules' => 8 }).first
+    )
+  end
+
+  def test_it_handles_nested_refs
+    schema = JSONSchemer.schema(Pathname.new(__dir__).join('schemas', 'nested_ref1.json'))
+    assert(schema.valid?(1))
+    refute(schema.valid?('1'))
+  end
+
+  def test_it_handles_json_pointer_refs_with_special_characters
+    schema = JSONSchemer.schema({
+      'type' => 'object',
+      'properties' => { 'foo' => { '$ref' => '#/definitions/~1some~1{id}'} },
+      'definitions' => { '/some/{id}' => { 'type' => 'string' } }
+    })
+    assert(schema.valid?({ 'foo' => 'bar' }))
+    refute(schema.valid?({ 'foo' => 1 }))
+  end
+
+  def test_it_handles_spaces_in_schema_path
+    schema = JSONSchemer.schema(Pathname.new(__dir__).join('schemas', 'sp ce', 'sp ce.json'))
+    assert schema.valid?('yes')
+    refute schema.valid?(0)
+  end
+
+  def test_json_schema_test_suite
+    {
+      'draft4' => JSONSchemer::Schema::Draft4,
+      'draft6' => JSONSchemer::Schema::Draft6,
+      'draft7' => JSONSchemer::Schema::Draft7
+    }.each do |version, draft_class|
+      output = Dir["JSON-Schema-Test-Suite/tests/#{version}/**/*.json"].each_with_object({}) do |file, file_output|
+        file_output[file] = JSON.parse(File.read(file)).map do |defn|
+          defn.fetch('tests').map do |test|
+            errors = draft_class.new(
+              defn.fetch('schema'),
+              ref_resolver: proc do |uri|
+                # Resolve localhost test schemas
+                if uri.host == 'localhost'
+                  path = Pathname.new(__dir__).join('..', 'JSON-Schema-Test-Suite', 'remotes', uri.path.gsub(/\A\//, ''))
+                  JSON.parse(path.read)
+                else
+                  response = Net::HTTP.get_response(uri)
+                  if response.is_a?(Net::HTTPRedirection)
+                    response = Net::HTTP.get_response(URI.parse(response.fetch('location')))
+                  end
+                  JSON.parse(response.body)
+                end
+              end
+            ).validate(test.fetch('data')).to_a
+            if test.fetch('valid')
+              assert_empty(errors, file)
+            else
+              refute_empty(errors, file)
+            end
+            errors
+          end
+        end
+      end
+      fixture = Pathname.new(__dir__).join('fixtures', "#{version}.json")
+      if ENV['WRITE_FIXTURES'] == 'true'
+        fixture.write("#{JSON.pretty_generate(output)}\n")
+      else
+        assert_equal(output, JSON.parse(fixture.read))
+      end
+    end
+  end
+
+  def test_it_validates_correctly_custom_keywords
+    root = {
+      'type' => 'number',
+      'even' => true
+    }
+    options = {
+      keywords: {
+        'even' => lambda do |data, curr_schema, _pointer|
+          if curr_schema['even']
+            data.to_i.even?
+          else
+            data.to_i.odd?
+          end
+        end
+      }
+    }
+
+    schema = JSONSchemer.schema(root, **options)
+    assert(schema.valid?(2))
+    refute(schema.valid?(3))
+  end
+
+  def test_it_handles_multiple_of_floats
+    assert(JSONSchemer.schema({ 'multipleOf' => 0.01 }).valid?(8.61))
+    refute(JSONSchemer.schema({ 'multipleOf' => 0.01 }).valid?(8.666))
+    assert(JSONSchemer.schema({ 'multipleOf' => 0.001 }).valid?(8.666))
+  end
+
+  def test_it_escapes_json_pointer_tokens
+    schemer = JSONSchemer.schema(
+      {
+        'type' => 'object',
+        'properties' => {
+          'foo/bar~' => {
+            'type' => 'string'
+          }
+        }
+    }
+    )
+    errors = schemer.validate({ 'foo/bar~' => 1 }).to_a
+    assert_equal(1, errors.size)
+    assert_equal('/foo~1bar~0', errors.first.fetch('data_pointer'))
+    assert_equal('/properties/foo~1bar~0', errors.first.fetch('schema_pointer'))
+  end
+end
diff --git a/test/pretty_errors_test.rb b/test/pretty_errors_test.rb
new file mode 100644
index 0000000..b03662e
--- /dev/null
+++ b/test/pretty_errors_test.rb
@@ -0,0 +1,102 @@
+require 'test_helper'
+
+class PrettyErrorsTest < Minitest::Test
+  def test_required_message
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'one' => { 'type' => 'string' }
+        },
+        'required' => %w[one]
+      }
+    )
+    error = schema.validate({ 'two' => 'optional' }).to_a.first
+    assert_equal("root is missing required keys: one", JSONSchemer::Errors.pretty(error))
+  end
+
+  def test_basic_type_message
+    %w[string integer number boolean null object].each do |type|
+      schema = JSONSchemer.schema(
+        {
+          'properties' => {
+            'one' => { 'type' => type }
+          }
+        }
+      )
+      error = schema.validate({ 'one' => ['wrong'] }).to_a.first
+      assert_equal("property '/one' is not of type: #{type}", JSONSchemer::Errors.pretty(error))
+    end
+  end
+
+  def test_array_message
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'one' => { 'type' => 'array' }
+        }
+      }
+    )
+    error = schema.validate({ 'one' => 'wrong' }).to_a.first
+    assert_equal("property '/one' is not of type: array", JSONSchemer::Errors.pretty(error))
+  end
+
+  def test_format_message
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'one' => {
+            'type' => 'string',
+            'format' => 'date-time'
+          }
+        }
+      }
+    )
+    error = schema.validate({ 'one' => 'abc' }).to_a.first
+    assert_equal("property '/one' does not match format: date-time", JSONSchemer::Errors.pretty(error))
+  end
+
+  def test_pattern_message
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'one' => {
+            'type' => 'string',
+            'pattern' => '\d+'
+          }
+        }
+      }
+    )
+    error = schema.validate({ 'one' => 'abc' }).to_a.first
+    assert_equal("property '/one' does not match pattern: \\d+", JSONSchemer::Errors.pretty(error))
+  end
+
+  def test_enum_message
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'one' => {
+            'type' => 'string',
+            'enum' => %w[one two]
+          }
+        }
+      }
+    )
+    error = schema.validate({ 'one' => 'abc' }).to_a.first
+    assert_equal("property '/one' is not one of: [\"one\", \"two\"]", JSONSchemer::Errors.pretty(error))
+  end
+
+  def test_const_message
+    schema = JSONSchemer.schema(
+      {
+        'properties' => {
+          'one' => {
+            'type' => 'string',
+            'const' => 'one'
+          }
+        }
+      }
+    )
+    error = schema.validate({ 'one' => 'abc' }).to_a.first
+    assert_equal("property '/one' is not: \"one\"", JSONSchemer::Errors.pretty(error))
+  end
+end
diff --git a/test/schemas/file_uri_ref_invalid_host.json b/test/schemas/file_uri_ref_invalid_host.json
new file mode 100644
index 0000000..f086f5d
--- /dev/null
+++ b/test/schemas/file_uri_ref_invalid_host.json
@@ -0,0 +1 @@
+{ "$ref": "file://host/path" }
diff --git a/test/schemas/file_uri_ref_invalid_scheme.json b/test/schemas/file_uri_ref_invalid_scheme.json
new file mode 100644
index 0000000..4f0ebb4
--- /dev/null
+++ b/test/schemas/file_uri_ref_invalid_scheme.json
@@ -0,0 +1 @@
+{ "$ref": "ftp://path" }
diff --git a/test/schemas/nested_ref1.json b/test/schemas/nested_ref1.json
new file mode 100644
index 0000000..fa34208
--- /dev/null
+++ b/test/schemas/nested_ref1.json
@@ -0,0 +1,3 @@
+{
+  "$ref": "nested_ref2.json"
+}
diff --git a/test/schemas/nested_ref2.json b/test/schemas/nested_ref2.json
new file mode 100644
index 0000000..2b46826
--- /dev/null
+++ b/test/schemas/nested_ref2.json
@@ -0,0 +1,12 @@
+{
+  "definitions": {
+    "nested": {
+      "$ref": "nested_ref3.json"
+    }
+  },
+  "allOf": [
+    {
+      "$ref": "#/definitions/nested"
+    }
+  ]
+}
diff --git a/test/schemas/nested_ref3.json b/test/schemas/nested_ref3.json
new file mode 100644
index 0000000..3ab970e
--- /dev/null
+++ b/test/schemas/nested_ref3.json
@@ -0,0 +1,3 @@
+{
+  "type": "number"
+}
diff --git a/test/schemas/schema1.json b/test/schemas/schema1.json
new file mode 100644
index 0000000..a98c746
--- /dev/null
+++ b/test/schemas/schema1.json
@@ -0,0 +1,8 @@
+{
+  "type": "object",
+  "allOf": [{ "$ref": "subschemas/schema2.json" }],
+  "properties": {
+    "a": { "$ref": "./subschemas/schema3.json" }
+  },
+  "required": ["a"]
+}
diff --git a/test/schemas/sp ce/sp ce.json b/test/schemas/sp ce/sp ce.json
new file mode 100644
index 0000000..7d78eb3
--- /dev/null
+++ b/test/schemas/sp ce/sp ce.json	
@@ -0,0 +1 @@
+{ "type": "string" }
diff --git a/test/schemas/subschemas/schema2.json b/test/schemas/subschemas/schema2.json
new file mode 100644
index 0000000..c750681
--- /dev/null
+++ b/test/schemas/subschemas/schema2.json
@@ -0,0 +1,9 @@
+{
+  "type": "object",
+  "properties": {
+    "id": { "type": "integer" }
+  },
+  "required": [
+    "id"
+  ]
+}
diff --git a/test/schemas/subschemas/schema3.json b/test/schemas/subschemas/schema3.json
new file mode 100644
index 0000000..28ac6e8
--- /dev/null
+++ b/test/schemas/subschemas/schema3.json
@@ -0,0 +1,3 @@
+{
+  "type": "string"
+}
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 0000000..ba0bf76
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,4 @@
+$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
+require "json_schemer"
+
+require "minitest/autorun"

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/cached_resolver.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/errors.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/format.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/schema/base.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/schema/draft4.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/schema/draft6.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/schema/draft7.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/lib/json_schemer/version.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/specifications/json_schemer-0.2.24.gemspec
-rwxr-xr-x  root/root   /usr/bin/json_schemer
-rwxr-xr-x  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/bin/rake
-rwxr-xr-x  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.24/exe/json_schemer

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/cached_ref_resolver.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/errors.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/format.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/schema/base.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/schema/draft4.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/schema/draft6.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/schema/draft7.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/gems/json_schemer-0.2.18/lib/json_schemer/version.rb
-rw-r--r--  root/root   /usr/share/rubygems-integration/all/specifications/json_schemer-0.2.18.gemspec

Control files: lines which differ (wdiff format)

  • Depends: ruby, ruby-ecma-re-validator (>= 0.3), ruby-hana (>= 1.3), ruby-uri-template (>= 0.7), ruby-regexp-parser (>= 2.0)

More details

Full run details