diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown index 7439163c..0329cfaf 100644 --- a/CONTRIBUTING.markdown +++ b/CONTRIBUTING.markdown @@ -14,7 +14,9 @@ make nmake ``` -The default target will build the project and run the test suite. +The default target will build the project and run the test suite. You will also +find the CLI binary under `build/`. The specific location varies depending on +your CMake default generator. Grant of Rights --------------- diff --git a/README.markdown b/README.markdown index 6b62a5a7..bed3e61e 100644 --- a/README.markdown +++ b/README.markdown @@ -67,11 +67,6 @@ documentation: - [Bundling](./docs/bundle.markdown) - [Framing](./docs/frame.markdown) -The following global options apply to all commands: - -- `--verbose / -v`: Enable verbose output -- `--resolve / -r`: Import the given JSON Schema into the resolution context - Coming Soon ----------- diff --git a/docs/bundle.markdown b/docs/bundle.markdown index 1fce733d..f306df81 100644 --- a/docs/bundle.markdown +++ b/docs/bundle.markdown @@ -2,21 +2,82 @@ Bundling ======== ```sh -jsonschema bundle +jsonschema bundle [--http/-h] [--verbose/-v] [--resolve/-r ...] ``` -A schema may contain references to remote schemas located in other files or -even shared over the Internet. JSON Schema supports a standardized process, -referred to as +A schema may contain references to remote schemas outside the scope of the +given schema. These remote schemas may live in other files, or may be server by +others over the Internet. JSON Schema supports a standardized process, referred +to as [bundling](https://json-schema.org/blog/posts/bundling-json-schema-compound-documents), -to resolve remote references in advance and inline them into the given schema. -The JSON Schema CLI supports this functionality through the `bundle` command. +to resolve remote references in advance and inline them into the given schema +for local consumption or further distribution. The JSON Schema CLI supports +this functionality through the `bundle` command. Examples -------- -### Bundle a JSON Schema preloading another one +For example, consider the following schema that references a +`https://example.com/string` remote schema: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$ref": "https://example.com/string" +} +``` + +The referenced schema is defined in a `string.json` file that looks like this: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/string", + "type": "string" +} +``` + +We can bundle the former schema by registering the latter schema into the +resolution context using the `--resolve / -r` option as follows: + +```sh +jsonschema bundle schema.json --resolve string.json +``` + +The resulting schema, which will be printed to standard output, would look like +this: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$ref": "https://example.com/string", + "$defs": { + "https://example.com/string": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/string", + "type": "string" + } + } +} +``` + +### Bundle a JSON Schema importing a single local schema ```sh jsonschema bundle path/to/my/schema.json --resolve path/to/external.json ``` + +### Bundle a JSON Schema importing multiple local schemas + +```sh +jsonschema bundle path/to/my/schema.json \ + --resolve path/to/one.json \ + --resolve path/to/two.json \ + --resolve path/to/three.json +``` + +### Bundle a JSON Schema while enabling HTTP resolution + +```sh +jsonschema bundle path/to/my/schema.json --http +``` diff --git a/docs/format.markdown b/docs/format.markdown index e5dc7fe5..db8a9595 100644 --- a/docs/format.markdown +++ b/docs/format.markdown @@ -2,7 +2,7 @@ Formatting ========== ```sh -jsonschema fmt [schemas-or-directories...] [--check|-c] +jsonschema fmt [schemas-or-directories...] [--check|-c] [--verbose/-v] ``` Schemas are code. As such, they are expected follow consistent stylistic diff --git a/docs/frame.markdown b/docs/frame.markdown index 8b6a8cf4..4a0e3844 100644 --- a/docs/frame.markdown +++ b/docs/frame.markdown @@ -2,7 +2,7 @@ Framing ======= ```sh -jsonschema frame +jsonschema frame [--verbose/-v] ``` To evaluate a schema, an implementation will first scan it to determine the @@ -16,7 +16,7 @@ is often useful for debugging purposes. Examples -------- -For example, consider the following schema with a local reference: +For example, consider the following schema that includes a local reference: ```json { diff --git a/docs/lint.markdown b/docs/lint.markdown index 5ddc0e9d..3af9a050 100644 --- a/docs/lint.markdown +++ b/docs/lint.markdown @@ -2,18 +2,47 @@ Linting ======= ```sh -jsonschema lint [schemas-or-directories...] [--fix|-f] +jsonschema lint [schemas-or-directories...] [--fix|-f] [--verbose/-v] ``` JSON Schema is a surprisingly expressive schema language. Like with traditional -programming languages, writing efficient and maintainable schemas take -experience, and there are lots of ways of doing it wrong. To help with this, -the JSON Schema CLI provides a `lint` command that can check your schemas -against various common anti-patterns and automatically fix many of them. +programming languages, writing efficient and maintainable schemas takes +experience, and there are lots of common pitfalls. Just like popular linters +like [ESLint](https://eslint.org), +[ClangTidy](https://clang.llvm.org/extra/clang-tidy/), and +[PyLint](https://www.pylint.org), the JSON Schema CLI provides a `lint` command +that can check your schemas against various common anti-patterns and +automatically fix many of them. Examples -------- +For example, consider the following schema that asserts that the JSON instance +is the string `foo`: + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "enum": [ "foo" ] +} +``` + +While this schema is technically correct, the JSON Schema 2020-12 dialect has a +[`const`](https://www.learnjsonschema.com/2020-12/validation/const/) keyword +that better expresses the intention of matching a single possible value. + +Running the JSON Schema CLI linter against the previous schema will produce the +following output: + +```sh +$ jsonschema lint schema.json +schema.json + An `enum` of a single value can be expressed as `const` (enum_to_const) +``` + +Furthermore, running the `lint` command with the `--fix / -f` option will +result in the JSON Schema CLI *automatically* fixing the warning for you. + ### Lint JSON Schemas in-place ```sh diff --git a/docs/test.markdown b/docs/test.markdown index 7803d14b..35270346 100644 --- a/docs/test.markdown +++ b/docs/test.markdown @@ -1,13 +1,19 @@ Testing ======= +> [!WARNING] +> Only JSON Schema Draft 4 is supported at this point in time. We have plans +> to support *every* dialect of JSON Schema from Draft 0 to Draft 2020-12 soon. + ```sh -jsonschema test [schemas-or-directories...] +jsonschema test [schemas-or-directories...] [--http/-h] [--metaschema/-m] [--verbose/-v] [--resolve/-r ...] ``` Schemas are code. As such, you should run an automated unit testing suite -against them. The JSON Schema CLI provides a schema-oriented test runner -inspired by the [official JSON Schema test +against them. Just like popular test frameworks like [Jest](https://jestjs.io), +[GoogleTest](https://google.github.io/googletest/), and +[PyTest](https://docs.pytest.org), the JSON Schema CLI provides a +schema-oriented test runner inspired by the [official JSON Schema test suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite). Examples @@ -41,3 +47,39 @@ Assuming this file is saved as `test/draft4.json`, you can run it as follows: ```sh jsonschema test test/draft4.json ``` + +### Run a single test definition + +```sh +jsonschema test path/to/test.json +``` + +### Run every `.json` test definition in a given directory (recursively) + +```sh +jsonschema test path/to/tests/ +``` + +### Run every `.json` test definition in the current directory (recursively) + +```sh +jsonschema test +``` + +### Run a single test definition validating the schemas against their metaschemas + +```sh +jsonschema test path/to/test.json --metaschema +``` + +### Run a single test definition enabling HTTP resolution + +```sh +jsonschema test path/to/test.json --http +``` + +### Run a single test definition importing a single local schema + +```sh +jsonschema test path/to/test.json --resolve path/to/external.json +``` diff --git a/docs/validate.markdown b/docs/validate.markdown index 3d957f7d..aeb1432d 100644 --- a/docs/validate.markdown +++ b/docs/validate.markdown @@ -1,19 +1,75 @@ Validating ========== +> [!WARNING] +> Only JSON Schema Draft 4 is supported at this point in time. We have plans +> to support *every* dialect of JSON Schema from Draft 0 to Draft 2020-12 soon. + ```sh -jsonschema validate +jsonschema validate [instance.json] [--http/-h] [--metaschema/-m] [--verbose/-v] [--resolve/-r ...] ``` The most popular use case of JSON Schema is to validate JSON documents. The -JSON Schema CLI offers a `validate` command to do exactly that. +JSON Schema CLI offers a `validate` command to evaluate a JSON instance against +a JSON Schema or a JSON Schema against its meta-schema, presenting +human-friendly information on unsuccessful validation. Examples -------- -### Validate a JSON instance +For example, consider the following JSON Schema Draft 4 schema that asserts +that the JSON instance is a string: + +```json +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "string" +} +``` + +Also consider a JSON instance called `instance.json` that looks like this: + +```json +12345 +``` + +This instance is an integer, while the given schema expects a string. +Validating the instance against the schema using the JSON Schema CLI will +result in the following output: + +```sh +$ jsonschema validate schema.json instance.json +error: The target document is expected to be of the given type + at instance location "" + at evaluate path "/type" +``` + +### Validate a JSON instance against a schema ```sh jsonschema validate path/to/my/schema.json path/to/my/instance.json ``` +### Validate a JSON Schema against it meta-schema + +```sh +jsonschema validate path/to/my/schema.json +``` + +### Validate a JSON instance against a schema plus the schema against its meta-schema + +```sh +jsonschema validate path/to/my/schema.json path/to/my/instance.json --metaschema +``` + +### Validate a JSON instance enabling HTTP resolution + +```sh +jsonschema validate path/to/my/schema.json path/to/my/instance.json --http +``` + +### Validate a JSON instance importing a single local schema + +```sh +jsonschema validate path/to/my/schema.json path/to/my/instance.json --resolve path/to/external.json +``` diff --git a/src/main.cc b/src/main.cc index 4ffe2712..e02ca0f3 100644 --- a/src/main.cc +++ b/src/main.cc @@ -29,7 +29,7 @@ Global Options: is valid with respects to its dialect metaschema even if an instance was passed. - test [schema.json...] [--http/-h] [--metaschema/-m] + test [schemas-or-directories...] [--http/-h] [--metaschema/-m] A schema test runner inspired by the official JSON Schema test suite. Passing directories as input will run every `.json` file in such @@ -39,7 +39,7 @@ Global Options: protocol. The `--metaschema/-m` option checks that the given schema is valid with respects to its dialect metaschema. - fmt [schema.json...] [--check/-c] + fmt [schemas-or-directories...] [--check/-c] Format the input schemas in-place. Passing directories as input means to format every `.json` file in such directory (recursively). If no @@ -47,7 +47,7 @@ Global Options: directory (recursively). The `--check/-c` option will check if the given schemas adhere to the desired formatting without modifying them. - lint [schema.json...] [--fix/-f] + lint [schemas-or-directories...] [--fix/-f] Lint the input schemas. Passing directories as input means to lint every `.json` file in such directory (recursively). If no argument is @@ -68,6 +68,7 @@ Global Options: Frame a schema in-place, displaying schema locations and references in a human-readable manner. +For more documentation, visit https://github.com/Intelligence-AI/jsonschema )EOF"}; auto jsonschema_main(const std::string &program, const std::string &command,