diff --git a/src/json-validator.cpp b/src/json-validator.cpp index 583ea40..3fb9693 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -102,7 +102,7 @@ namespace nlohmann namespace json_schema { -class root_schema : public schema +class root_schema { schema_loader loader_; format_checker format_check_; @@ -133,8 +133,7 @@ public: format_checker &&format, content_checker &&content) - : schema(this), - loader_(std::move(loader)), + : loader_(std::move(loader)), format_check_(std::move(format)), content_check_(std::move(content)) { @@ -280,22 +279,31 @@ public: "' has still undefined references."); } - void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final + void validate(const json::json_pointer &ptr, + const json &instance, + json_patch &patch, + error_handler &e, + const json_uri &initial) const { - if (root_) - root_->validate(ptr, instance, patch, e); - else + if (!root_) { e.error(ptr, "", "no root schema has yet been set for validating an instance"); - } + return; + } - const json &defaultValue(const json::json_pointer &ptr, const json &instance, error_handler &e) const override - { - if (root_) - return root_->defaultValue(ptr, instance, e); - else - e.error(ptr, "", "no root schema has yet been set for validating an instance"); + auto file_entry = files_.find(initial.location()); + if (file_entry == files_.end()) { + e.error(ptr, "", "no file found serving requested root-URI. " + initial.location()); + return; + } - return EmptyDefault; + auto &file = file_entry->second; + auto sch = file.schemas.find(initial.fragment()); + if (sch == file.schemas.end()) { + e.error(ptr, "", "no schema find for request initial URI: " + initial.to_string()); + return; + } + + sch->second->validate(ptr, instance, patch, e); } }; @@ -1356,11 +1364,11 @@ json json_validator::validate(const json &instance) const return validate(instance, err); } -json json_validator::validate(const json &instance, error_handler &err) const +json json_validator::validate(const json &instance, error_handler &err, const json_uri &initial_uri) const { json::json_pointer ptr; json_patch patch; - root_->validate(ptr, instance, patch, err); + root_->validate(ptr, instance, patch, err, initial_uri); return patch; } diff --git a/src/nlohmann/json-schema.hpp b/src/nlohmann/json-schema.hpp index e99c400..425d30f 100644 --- a/src/nlohmann/json-schema.hpp +++ b/src/nlohmann/json-schema.hpp @@ -189,7 +189,7 @@ public: json validate(const json &) const; // validate a json-document based on the root-schema with a custom error-handler - json validate(const json &, error_handler &) const; + json validate(const json &, error_handler &, const json_uri &initial_uri = json_uri("#")) const; }; } // namespace json_schema diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d82f41d..8b45790 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,3 +65,7 @@ add_executable(binary-validation binary-validation.cpp) target_include_directories(binary-validation PRIVATE ${PROJECT_SOURCE_DIR}/src) target_link_libraries(binary-validation PRIVATE nlohmann_json_schema_validator) add_test(NAME binary-validation COMMAND binary-validation) + +add_executable(issue-149-entry-selection issue-149-entry-selection.cpp) +target_link_libraries(issue-149-entry-selection PRIVATE nlohmann_json_schema_validator) +add_test(NAME issue-149-entry-selection COMMAND issue-149-entry-selection) diff --git a/test/issue-149-entry-selection.cpp b/test/issue-149-entry-selection.cpp new file mode 100644 index 0000000..c54c2c4 --- /dev/null +++ b/test/issue-149-entry-selection.cpp @@ -0,0 +1,93 @@ +#include + +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +namespace +{ + +static int error_count; +#define EXPECT_EQ(a, b) \ + do { \ + if (a != b) { \ + std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; \ + error_count++; \ + } \ + } while (0) + +// The schema is defined based upon a string literal +static json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "integer", + "definitions": { + "A": { + "type": "object", + "properties": { + "b": { + "$ref": "#/definitions/B" + } + } + }, + "B": { + "type": "integer" + } + } +})"_json; + +class store_err_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, instance, message); + std::cerr << "ERROR: '" << ptr << "' - '" << instance << "': " << message << "\n"; + failed.push_back(ptr); + } + +public: + std::vector failed; + + void reset() override + { + nlohmann::json_schema::basic_error_handler::reset(); + failed.clear(); + } +}; + +} // namespace + +static json_validator validator(person_schema); + +int main(void) +{ + store_err_handler err; + + validator.validate(1, err); // OK + EXPECT_EQ(err.failed.size(), 0); + err.reset(); + + validator.validate("1", err); // no name + EXPECT_EQ(err.failed.size(), 1); + err.reset(); + + validator.validate(1, err, json_uri("#/definitions/B")); + EXPECT_EQ(err.failed.size(), 0); + err.reset(); + + validator.validate("1", err, json_uri("#/definitions/B")); + EXPECT_EQ(err.failed.size(), 1); + err.reset(); + + validator.validate({{"b", 1}}, err, json_uri("#/definitions/A")); + EXPECT_EQ(err.failed.size(), 0); + err.reset(); + + validator.validate({{"b", "1"}}, err, json_uri("#/definitions/A")); + EXPECT_EQ(err.failed.size(), 1); + err.reset(); + + return error_count; +}