-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expose JSON BinPack's canonicalizer as a
canonicalize
command (#165)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
- Loading branch information
Showing
85 changed files
with
6,500 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
if(NOT JSONBinPack_FOUND) | ||
set(JSONBINPACK_INSTALL OFF CACHE BOOL "disable installation") | ||
set(JSONBINPACK_CLI OFF CACHE BOOL "disable the JSON BinPack CLI module") | ||
set(JSONBINPACK_RUNTIME OFF CACHE BOOL "disable the JSON BinPack runtime module") | ||
add_subdirectory("${PROJECT_SOURCE_DIR}/vendor/jsonbinpack") | ||
set(JSONBinPack_FOUND ON) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
Canonicalize | ||
============ | ||
|
||
```sh | ||
jsonschema canonicalize <schema.json> | ||
``` | ||
|
||
JSON Schema is an extremely expressive schema language. As such, schema authors | ||
can express the same constraints in a variety of ways, making the process of | ||
statically analyzing schemas complex. This command attempts to tackle the | ||
problem by transforming a given JSON Schema into a simpler (but more verbose) | ||
normalized form referred to as _canonical_. | ||
|
||
> Refer to [Juan Cruz Viotti's dissertation on JSON | ||
> BinPack's](https://www.jviotti.com/dissertation.pdf) for how JSON Schema | ||
> canonicalization was originally defined. | ||
Examples | ||
-------- | ||
|
||
For example, consider the following simple schema: | ||
|
||
```json | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"properties": { | ||
"foo": { "type": "string" } | ||
} | ||
} | ||
``` | ||
|
||
The canonicalization process will result in something like this: | ||
|
||
``` | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"anyOf": [ | ||
{ | ||
"enum": [ | ||
null | ||
] | ||
}, | ||
{ | ||
"enum": [ | ||
false, | ||
true | ||
] | ||
}, | ||
{ | ||
"type": "object", | ||
"minProperties": 0, | ||
"properties": { | ||
"foo": { | ||
"type": "string", | ||
"minLength": 0 | ||
} | ||
} | ||
}, | ||
{ | ||
"type": "array", | ||
"minItems": 0 | ||
}, | ||
{ | ||
"type": "string", | ||
"minLength": 0 | ||
}, | ||
{ | ||
"type": "number", | ||
"multipleOf": 1 | ||
}, | ||
{ | ||
"type": "integer", | ||
"multipleOf": 1 | ||
} | ||
] | ||
} | ||
``` | ||
|
||
### Canonicalize a JSON Schema | ||
|
||
```sh | ||
jsonschema canonicalize path/to/my/schema.json | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include <sourcemeta/jsonbinpack/compiler.h> | ||
#include <sourcemeta/jsontoolkit/json.h> | ||
#include <sourcemeta/jsontoolkit/jsonschema.h> | ||
|
||
#include <cstdlib> // EXIT_SUCCESS | ||
#include <iostream> // std::cout, std::endl | ||
|
||
#include "command.h" | ||
#include "utils.h" | ||
|
||
auto sourcemeta::jsonschema::cli::canonicalize( | ||
const std::span<const std::string> &arguments) -> int { | ||
const auto options{parse_options(arguments, {})}; | ||
|
||
if (options.at("").size() < 1) { | ||
std::cerr | ||
<< "error: This command expects a path to a schema. For example:\n\n" | ||
<< " jsonschema canonicalize path/to/schema.json\n"; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
auto schema{sourcemeta::jsontoolkit::from_file(options.at("").front())}; | ||
sourcemeta::jsonbinpack::canonicalize( | ||
schema, sourcemeta::jsontoolkit::default_schema_walker, | ||
resolver(options, options.contains("h") || options.contains("http"))); | ||
sourcemeta::jsontoolkit::prettify( | ||
schema, std::cout, sourcemeta::jsontoolkit::schema_format_compare); | ||
std::cout << std::endl; | ||
return EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/bin/sh | ||
|
||
set -o errexit | ||
set -o nounset | ||
|
||
TMP="$(mktemp -d)" | ||
clean() { rm -rf "$TMP"; } | ||
trap clean EXIT | ||
|
||
"$1" canonicalize 2>"$TMP/stderr.txt" && CODE="$?" || CODE="$?" | ||
test "$CODE" = "1" || exit 1 | ||
|
||
cat << 'EOF' > "$TMP/expected.txt" | ||
error: This command expects a path to a schema. For example: | ||
jsonschema canonicalize path/to/schema.json | ||
EOF | ||
|
||
diff "$TMP/stderr.txt" "$TMP/expected.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/bin/sh | ||
|
||
set -o errexit | ||
set -o nounset | ||
|
||
TMP="$(mktemp -d)" | ||
clean() { rm -rf "$TMP"; } | ||
trap clean EXIT | ||
|
||
cat << 'EOF' > "$TMP/schema.json" | ||
{ | ||
"type" string | ||
} | ||
EOF | ||
|
||
"$1" canonicalize "$TMP/schema.json" 2>"$TMP/stderr.txt" \ | ||
&& CODE="$?" || CODE="$?" | ||
test "$CODE" = "1" || exit 1 | ||
|
||
cat << EOF > "$TMP/expected.txt" | ||
error: Failed to parse the JSON document at line 2 and column 10 | ||
$(realpath "$TMP")/schema.json | ||
EOF | ||
|
||
diff "$TMP/stderr.txt" "$TMP/expected.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/bin/sh | ||
|
||
set -o errexit | ||
set -o nounset | ||
|
||
TMP="$(mktemp -d)" | ||
clean() { rm -rf "$TMP"; } | ||
trap clean EXIT | ||
|
||
cat << 'EOF' > "$TMP/schema.json" | ||
{ | ||
"$schema": "https://example.com/unknown", | ||
"$id": "https://example.com", | ||
"$ref": "nested" | ||
} | ||
EOF | ||
|
||
"$1" canonicalize "$TMP/schema.json" 2>"$TMP/stderr.txt" && CODE="$?" || CODE="$?" | ||
test "$CODE" = "1" || exit 1 | ||
|
||
cat << EOF > "$TMP/expected.txt" | ||
error: Could not resolve the requested schema | ||
at https://example.com/unknown | ||
EOF | ||
|
||
diff "$TMP/stderr.txt" "$TMP/expected.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/bin/sh | ||
|
||
set -o errexit | ||
set -o nounset | ||
|
||
TMP="$(mktemp -d)" | ||
clean() { rm -rf "$TMP"; } | ||
trap clean EXIT | ||
|
||
cat << 'EOF' > "$TMP/schema.json" | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"properties": { | ||
"foo": { "type": "string" } | ||
} | ||
} | ||
EOF | ||
|
||
"$1" canonicalize "$TMP/schema.json" > "$TMP/result.json" | ||
|
||
cat "$TMP/result.json" | ||
|
||
cat << 'EOF' > "$TMP/expected.json" | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"anyOf": [ | ||
{ | ||
"enum": [ | ||
null | ||
] | ||
}, | ||
{ | ||
"enum": [ | ||
false, | ||
true | ||
] | ||
}, | ||
{ | ||
"type": "object", | ||
"minProperties": 0, | ||
"properties": { | ||
"foo": { | ||
"type": "string", | ||
"minLength": 0 | ||
} | ||
} | ||
}, | ||
{ | ||
"type": "array", | ||
"minItems": 0 | ||
}, | ||
{ | ||
"type": "string", | ||
"minLength": 0 | ||
}, | ||
{ | ||
"type": "number", | ||
"multipleOf": 1 | ||
}, | ||
{ | ||
"type": "integer", | ||
"multipleOf": 1 | ||
} | ||
] | ||
} | ||
EOF | ||
|
||
diff "$TMP/result.json" "$TMP/expected.json" |
Oops, something went wrong.