From 408d2901629c5aa6ef169ed7cd92810eef958385 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 13 Jan 2025 14:17:16 -0400 Subject: [PATCH] Consider `.json` as a fallback on `FlatFileSchemaResolver` Signed-off-by: Juan Cruz Viotti --- src/jsonschema/resolver.cc | 9 ++++++- .../jsonschema_flat_file_resolver_test.cc | 24 +++++++++++++++++++ .../schemas/2020-12-without-extension.json | 4 ++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/jsonschema/schemas/2020-12-without-extension.json diff --git a/src/jsonschema/resolver.cc b/src/jsonschema/resolver.cc index 76577e052..34ab0137a 100644 --- a/src/jsonschema/resolver.cc +++ b/src/jsonschema/resolver.cc @@ -136,7 +136,14 @@ auto FlatFileSchemaResolver::reidentify(const std::string &schema, auto FlatFileSchemaResolver::operator()(std::string_view identifier) const -> std::optional { const std::string string_identifier{to_lowercase(identifier)}; - const auto result{this->schemas.find(string_identifier)}; + auto result{this->schemas.find(string_identifier)}; + + // Try with a `.json` extension (if not already) as a fallback, given + // how common that case is when using a file-based resolver + if (result == this->schemas.cend() && !string_identifier.ends_with(".json")) { + result = this->schemas.find(string_identifier + ".json"); + } + if (result != this->schemas.cend()) { auto schema{sourcemeta::jsontoolkit::from_file(result->second.path)}; assert(sourcemeta::jsontoolkit::is_schema(schema)); diff --git a/test/jsonschema/jsonschema_flat_file_resolver_test.cc b/test/jsonschema/jsonschema_flat_file_resolver_test.cc index 51e8373df..052542308 100644 --- a/test/jsonschema/jsonschema_flat_file_resolver_test.cc +++ b/test/jsonschema/jsonschema_flat_file_resolver_test.cc @@ -48,6 +48,30 @@ TEST(JSONSchema_FlatFileSchemaResolver, single_schema_with_default_dialect) { expected); } +TEST(JSONSchema_FlatFileSchemaResolver, no_json_extension_on_insert) { + sourcemeta::jsontoolkit::FlatFileSchemaResolver resolver; + const auto schema_path{std::filesystem::path{SCHEMAS_PATH} / + "2020-12-without-extension.json"}; + const auto &identifier{resolver.add(schema_path)}; + EXPECT_EQ(identifier, "https://www.sourcemeta.com/2020-12-without-extension"); + EXPECT_TRUE(resolver("https://www.sourcemeta.com/2020-12-without-extension") + .has_value()); + EXPECT_EQ( + resolver("https://www.sourcemeta.com/2020-12-without-extension").value(), + sourcemeta::jsontoolkit::from_file(schema_path)); +} + +TEST(JSONSchema_FlatFileSchemaResolver, no_json_extension_on_lookup) { + sourcemeta::jsontoolkit::FlatFileSchemaResolver resolver; + const auto schema_path{std::filesystem::path{SCHEMAS_PATH} / + "2020-12-id.json"}; + const auto &identifier{resolver.add(schema_path)}; + EXPECT_EQ(identifier, "https://www.sourcemeta.com/2020-12-id.json"); + EXPECT_TRUE(resolver("https://www.sourcemeta.com/2020-12-id").has_value()); + EXPECT_EQ(resolver("https://www.sourcemeta.com/2020-12-id").value(), + sourcemeta::jsontoolkit::from_file(schema_path)); +} + TEST(JSONSchema_FlatFileSchemaResolver, single_schema_anonymous_with_default) { sourcemeta::jsontoolkit::FlatFileSchemaResolver resolver; const auto schema_path{std::filesystem::path{SCHEMAS_PATH} / diff --git a/test/jsonschema/schemas/2020-12-without-extension.json b/test/jsonschema/schemas/2020-12-without-extension.json new file mode 100644 index 000000000..953fe326a --- /dev/null +++ b/test/jsonschema/schemas/2020-12-without-extension.json @@ -0,0 +1,4 @@ +{ + "$id": "https://www.sourcemeta.com/2020-12-without-extension", + "$schema": "https://json-schema.org/draft/2020-12/schema" +}