Skip to content

Commit 61544bb

Browse files
authored
Introduce a new --default-dialect option for most commands (#292)
See: #218 Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent e3d8dcc commit 61544bb

26 files changed

+354
-35
lines changed

docs/bundle.markdown

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Bundling
55
jsonschema bundle <schema.json|.yaml>
66
[--http/-h] [--verbose/-v] [--resolve/-r <schemas-or-directories> ...]
77
[--extension/-e <extension>] [--ignore/-i <schemas-or-directories>]
8-
[--without-id/-w]
8+
[--without-id/-w] [--default-dialect, -d <uri>]
99
```
1010

1111
A schema may contain references to remote schemas outside the scope of the

docs/decode.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Decode
33

44
```sh
55
jsonschema decode <output.binpack> <output.json|.jsonl>
6+
[--default-dialect, -d <uri>]
67
```
78

89
This command decodes a JSON document using [JSON

docs/encode.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Encode
33

44
```sh
55
jsonschema encode <document.json|.jsonl> <output.binpack>
6+
[--default-dialect, -d <uri>]
67
```
78

89
This command encodes a JSON document using [JSON

docs/inspect.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Framing
33

44
```sh
55
jsonschema inspect <schema.json|.yaml> [--json/-j] [--verbose/-v]
6+
[--default-dialect, -d <uri>]
67
```
78

89
To evaluate a schema, an implementation will first scan it to determine the

docs/lint.markdown

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ Linting
22
=======
33

44
```sh
5-
jsonschema lint [schemas-or-directories...] [--fix/-f] [--json/-j]
6-
[--verbose/-v] [--resolve/-r <schemas-or-directories> ...]
5+
jsonschema lint [schemas-or-directories...] [--http/-h] [--fix/-f]
6+
[--json/-j] [--verbose/-v] [--resolve/-r <schemas-or-directories> ...]
77
[--extension/-e <extension>] [--ignore/-i <schemas-or-directories>]
88
[--exclude/-x <rule-name>] [--keep-ordering/-k]
9+
[--default-dialect, -d <uri>]
910
```
1011

1112
JSON Schema is a surprisingly expressive schema language. Like with traditional

docs/metaschema.markdown

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ Metaschema
66
77
```sh
88
jsonschema metaschema [schemas-or-directories...]
9-
[--verbose/-v] [--http/-h] [--extension/-e <extension>]
9+
[--http/-h] [--verbose/-v] [--extension/-e <extension>]
1010
[--ignore/-i <schemas-or-directories>] [--trace/-t]
11+
[--default-dialect, -d <uri>]
1112
```
1213

1314
Ensure that a schema or a set of schemas are considered valid with regards to

docs/test.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Testing
88
jsonschema test [schemas-or-directories...]
99
[--http/-h] [--verbose/-v] [--resolve/-r <schemas-or-directories> ...]
1010
[--extension/-e <extension>] [--ignore/-i <schemas-or-directories>]
11+
[--default-dialect, -d <uri>]
1112
```
1213

1314
Schemas are code. As such, you should run an automated unit testing suite

docs/validate.markdown

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ Validating
55
> JSON Schema Draft 3 and older are not supported at this point in time.
66
77
```sh
8-
jsonschema validate <schema.json|.yaml> <instance.json|.jsonl|.yaml...> [--http/-h]
9-
[--verbose/-v] [--resolve/-r <schemas-or-directories> ...] [--benchmark/-b]
10-
[--extension/-e <extension>] [--ignore/-i <schemas-or-directories>] [--trace/-t]
11-
[--fast/-f]
8+
jsonschema validate <schema.json|.yaml> <instance.json|.jsonl|.yaml...>
9+
[--http/-h] [--verbose/-v] [--resolve/-r <schemas-or-directories> ...]
10+
[--benchmark/-b] [--extension/-e <extension>]
11+
[--ignore/-i <schemas-or-directories>] [--trace/-t] [--fast/-f]
12+
[--default-dialect, -d <uri>]
1213
```
1314

1415
The most popular use case of JSON Schema is to validate JSON documents. The

src/command_bundle.cc

+7-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ auto sourcemeta::jsonschema::cli::bundle(
1111
const std::span<const std::string> &arguments) -> int {
1212
const auto options{
1313
parse_options(arguments, {"h", "http", "w", "without-id"})};
14+
const auto dialect{default_dialect(options)};
1415

1516
if (options.at("").size() < 1) {
1617
std::cerr
@@ -23,13 +24,17 @@ auto sourcemeta::jsonschema::cli::bundle(
2324

2425
sourcemeta::core::bundle(
2526
schema, sourcemeta::core::schema_official_walker,
26-
resolver(options, options.contains("h") || options.contains("http")));
27+
resolver(options, options.contains("h") || options.contains("http"),
28+
dialect),
29+
dialect);
2730

2831
if (options.contains("w") || options.contains("without-id")) {
2932
log_verbose(options) << "Removing schema identifiers\n";
3033
sourcemeta::core::unidentify(
3134
schema, sourcemeta::core::schema_official_walker,
32-
resolver(options, options.contains("h") || options.contains("http")));
35+
resolver(options, options.contains("h") || options.contains("http"),
36+
dialect),
37+
dialect);
3338
}
3439

3540
sourcemeta::core::prettify(schema, std::cout,

src/command_decode.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ auto sourcemeta::jsonschema::cli::decode(
4242
"$schema": "https://json-schema.org/draft/2020-12/schema"
4343
})JSON")};
4444

45+
const auto dialect{default_dialect(options)};
4546
sourcemeta::jsonbinpack::compile(
4647
schema, sourcemeta::core::schema_official_walker,
47-
resolver(options, options.contains("h") || options.contains("http")));
48+
resolver(options, options.contains("h") || options.contains("http"),
49+
dialect));
4850
const auto encoding{sourcemeta::jsonbinpack::load(schema)};
4951

5052
std::ifstream input_stream{sourcemeta::jsonschema::cli::safe_weakly_canonical(

src/command_encode.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ auto sourcemeta::jsonschema::cli::encode(
2929
"$schema": "https://json-schema.org/draft/2020-12/schema"
3030
})JSON")};
3131

32+
const auto dialect{default_dialect(options)};
3233
sourcemeta::jsonbinpack::compile(
3334
schema, sourcemeta::core::schema_official_walker,
34-
resolver(options, options.contains("h") || options.contains("http")));
35+
resolver(options, options.contains("h") || options.contains("http"),
36+
dialect));
3537
const auto encoding{sourcemeta::jsonbinpack::load(schema)};
3638

3739
const std::filesystem::path document{options.at("").front()};

src/command_inspect.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ auto sourcemeta::jsonschema::cli::inspect(
2222

2323
sourcemeta::core::SchemaFrame frame{
2424
sourcemeta::core::SchemaFrame::Mode::Instances};
25+
26+
const auto dialect{default_dialect(options)};
2527
frame.analyse(schema, sourcemeta::core::schema_official_walker,
26-
resolver(options));
28+
resolver(options,
29+
options.contains("h") || options.contains("http"),
30+
dialect),
31+
dialect);
2732

2833
if (options.contains("json") || options.contains("j")) {
2934
sourcemeta::core::prettify(frame.to_json(), std::cout);

src/command_lint.cc

+9-3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ auto sourcemeta::jsonschema::cli::lint(
6363

6464
bool result{true};
6565
auto errors_array = sourcemeta::core::JSON::make_array();
66+
const auto dialect{default_dialect(options)};
6667

6768
if (options.contains("f") || options.contains("fix")) {
6869
for (const auto &entry :
@@ -77,7 +78,10 @@ auto sourcemeta::jsonschema::cli::lint(
7778

7879
auto copy = entry.second;
7980
bundle.apply(copy, sourcemeta::core::schema_official_walker,
80-
resolver(options));
81+
resolver(options,
82+
options.contains("h") || options.contains("http"),
83+
dialect),
84+
dialect);
8185
std::ofstream output{entry.first};
8286
if (options.contains("k") || options.contains("keep-ordering")) {
8387
sourcemeta::core::prettify(copy, output);
@@ -93,7 +97,8 @@ auto sourcemeta::jsonschema::cli::lint(
9397
log_verbose(options) << "Linting: " << entry.first.string() << "\n";
9498
const bool subresult = bundle.check(
9599
entry.second, sourcemeta::core::schema_official_walker,
96-
resolver(options),
100+
resolver(options, options.contains("h") || options.contains("http"),
101+
dialect),
97102
[&](const auto &pointer, const auto &name, const auto &message) {
98103
if (output_json) {
99104
auto error_obj = sourcemeta::core::JSON::make_object();
@@ -116,7 +121,8 @@ auto sourcemeta::jsonschema::cli::lint(
116121
sourcemeta::core::stringify(pointer, std::cout);
117122
std::cout << "\"\n";
118123
}
119-
});
124+
},
125+
dialect);
120126

121127
if (!subresult) {
122128
result = false;

src/command_metaschema.cc

+8-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ auto sourcemeta::jsonschema::cli::metaschema(
1818
const std::span<const std::string> &arguments) -> int {
1919
const auto options{parse_options(arguments, {"h", "http", "t", "trace"})};
2020
const auto trace{options.contains("t") || options.contains("trace")};
21+
const auto default_dialect_option{default_dialect(options)};
2122
const auto custom_resolver{
22-
resolver(options, options.contains("h") || options.contains("http"))};
23+
resolver(options, options.contains("h") || options.contains("http"),
24+
default_dialect_option)};
2325
bool result{true};
2426
sourcemeta::blaze::Evaluator evaluator;
2527

@@ -37,16 +39,17 @@ auto sourcemeta::jsonschema::cli::metaschema(
3739
return EXIT_FAILURE;
3840
}
3941

40-
const auto dialect{sourcemeta::core::dialect(entry.second)};
42+
const auto dialect{
43+
sourcemeta::core::dialect(entry.second, default_dialect_option)};
4144
assert(dialect.has_value());
4245

43-
const auto metaschema{
44-
sourcemeta::core::metaschema(entry.second, custom_resolver)};
46+
const auto metaschema{sourcemeta::core::metaschema(
47+
entry.second, custom_resolver, default_dialect_option)};
4548
if (!cache.contains(dialect.value())) {
4649
const auto metaschema_template{sourcemeta::blaze::compile(
4750
metaschema, sourcemeta::core::schema_official_walker, custom_resolver,
4851
sourcemeta::blaze::default_schema_compiler,
49-
sourcemeta::blaze::Mode::Exhaustive)};
52+
sourcemeta::blaze::Mode::Exhaustive, default_dialect_option)};
5053
cache.insert({dialect.value(), metaschema_template});
5154
}
5255

src/command_test.cc

+5-3
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ auto sourcemeta::jsonschema::cli::test(
4444
const std::span<const std::string> &arguments) -> int {
4545
const auto options{parse_options(arguments, {"h", "http"})};
4646
bool result{true};
47-
const auto test_resolver{
48-
resolver(options, options.contains("h") || options.contains("http"))};
47+
const auto dialect{default_dialect(options)};
48+
const auto test_resolver{resolver(
49+
options, options.contains("h") || options.contains("http"), dialect)};
4950
const auto verbose{options.contains("verbose") || options.contains("v")};
5051
sourcemeta::blaze::Evaluator evaluator;
5152

@@ -117,7 +118,8 @@ auto sourcemeta::jsonschema::cli::test(
117118
try {
118119
schema_template = sourcemeta::blaze::compile(
119120
schema, sourcemeta::core::schema_official_walker, test_resolver,
120-
sourcemeta::blaze::default_schema_compiler);
121+
sourcemeta::blaze::default_schema_compiler,
122+
sourcemeta::blaze::Mode::FastValidation, dialect);
121123
} catch (const sourcemeta::core::SchemaReferenceError &error) {
122124
if (error.location() == sourcemeta::core::Pointer{"$ref"} &&
123125
error.id() == schema_uri.recompose()) {

src/command_validate.cc

+5-4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ auto sourcemeta::jsonschema::cli::validate(
3939
}
4040

4141
const auto &schema_path{options.at("").at(0)};
42-
const auto custom_resolver{
43-
resolver(options, options.contains("h") || options.contains("http"))};
42+
const auto dialect{default_dialect(options)};
43+
const auto custom_resolver{resolver(
44+
options, options.contains("h") || options.contains("http"), dialect)};
4445

4546
const auto schema{sourcemeta::jsonschema::cli::read_file(schema_path)};
4647

@@ -54,14 +55,14 @@ auto sourcemeta::jsonschema::cli::validate(
5455
}
5556

5657
const auto fast_mode{options.contains("f") || options.contains("fast")};
57-
5858
const auto benchmark{options.contains("b") || options.contains("benchmark")};
5959
const auto trace{options.contains("t") || options.contains("trace")};
6060
const auto schema_template{sourcemeta::blaze::compile(
6161
schema, sourcemeta::core::schema_official_walker, custom_resolver,
6262
sourcemeta::blaze::default_schema_compiler,
6363
fast_mode ? sourcemeta::blaze::Mode::FastValidation
64-
: sourcemeta::blaze::Mode::Exhaustive)};
64+
: sourcemeta::blaze::Mode::Exhaustive,
65+
dialect)};
6566
sourcemeta::blaze::Evaluator evaluator;
6667

6768
bool result{true};

src/main.cc

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
constexpr std::string_view USAGE_DETAILS{R"EOF(
1717
Global Options:
1818
19-
--verbose, -v Enable verbose output
20-
--resolve, -r Import the given JSON Schema (or directory of schemas)
21-
into the resolution context
19+
--verbose, -v Enable verbose output
20+
--resolve, -r Import the given JSON Schema (or directory of schemas)
21+
into the resolution context
22+
--default-dialect, -d <uri> Specify the URI for the default dialect to be used
23+
if the `$schema` keyword is not set
2224
2325
Commands:
2426

src/utils.cc

+20-3
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,9 @@ static auto fallback_resolver(
291291
}
292292

293293
auto resolver(const std::map<std::string, std::vector<std::string>> &options,
294-
const bool remote) -> sourcemeta::core::SchemaResolver {
294+
const bool remote,
295+
const std::optional<std::string> &default_dialect)
296+
-> sourcemeta::core::SchemaResolver {
295297
sourcemeta::core::SchemaMapResolver dynamic_resolver{
296298
[remote, &options](std::string_view identifier) {
297299
if (remote) {
@@ -307,7 +309,7 @@ auto resolver(const std::map<std::string, std::vector<std::string>> &options,
307309
parse_extensions(options))) {
308310
log_verbose(options) << "Importing schema into the resolution context: "
309311
<< entry.first.string() << "\n";
310-
dynamic_resolver.add(entry.second);
312+
dynamic_resolver.add(entry.second, default_dialect);
311313
}
312314
}
313315

@@ -317,7 +319,7 @@ auto resolver(const std::map<std::string, std::vector<std::string>> &options,
317319
parse_extensions(options))) {
318320
log_verbose(options) << "Importing schema into the resolution context: "
319321
<< entry.first.string() << "\n";
320-
dynamic_resolver.add(entry.second);
322+
dynamic_resolver.add(entry.second, default_dialect);
321323
}
322324
}
323325

@@ -393,4 +395,19 @@ auto safe_weakly_canonical(const std::filesystem::path &input)
393395
: std::filesystem::weakly_canonical(input);
394396
}
395397

398+
auto default_dialect(
399+
const std::map<std::string, std::vector<std::string>> &options)
400+
-> std::optional<std::string> {
401+
402+
if (options.contains("default-dialect")) {
403+
return options.at("default-dialect").front();
404+
}
405+
406+
if (options.contains("d")) {
407+
return options.at("d").front();
408+
}
409+
410+
return std::nullopt;
411+
}
412+
396413
} // namespace sourcemeta::jsonschema::cli

src/utils.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ auto print(const sourcemeta::blaze::TraceOutput &output, std::ostream &stream)
3737
-> void;
3838

3939
auto resolver(const std::map<std::string, std::vector<std::string>> &options,
40-
const bool remote = false) -> sourcemeta::core::SchemaResolver;
40+
const bool remote,
41+
const std::optional<std::string> &default_dialect)
42+
-> sourcemeta::core::SchemaResolver;
4143

4244
auto log_verbose(const std::map<std::string, std::vector<std::string>> &options)
4345
-> std::ostream &;
@@ -53,6 +55,10 @@ auto parse_ignore(
5355
auto safe_weakly_canonical(const std::filesystem::path &input)
5456
-> std::filesystem::path;
5557

58+
auto default_dialect(
59+
const std::map<std::string, std::vector<std::string>> &options)
60+
-> std::optional<std::string>;
61+
5662
} // namespace sourcemeta::jsonschema::cli
5763

5864
#endif

0 commit comments

Comments
 (0)