From 79639446a0dafa1023d2d850b45b74e06a022a67 Mon Sep 17 00:00:00 2001
From: Patrick Boettcher
Date: Mon, 14 Oct 2019 11:58:04 +0200
Subject: [PATCH] Add constructor taking a root-schema as argument
This way the validator can be used static/global loading once a root-schema.
As no try/catch-compound can be placed around, it has to be a valid schema.
Related to #70
---
src/json-schema.hpp | 1 +
src/json-validator.cpp | 6 ++
test/CMakeLists.txt | 4 +
test/issue-70-root-schema-constructor.cpp | 123 ++++++++++++++++++++++
4 files changed, 134 insertions(+)
create mode 100644 test/issue-70-root-schema-constructor.cpp
diff --git a/src/json-schema.hpp b/src/json-schema.hpp
index df088da..3bd319a 100644
--- a/src/json-schema.hpp
+++ b/src/json-schema.hpp
@@ -150,6 +150,7 @@ class JSON_SCHEMA_VALIDATOR_API json_validator
public:
json_validator(schema_loader = nullptr, format_checker = nullptr);
json_validator(json_validator &&);
+ json_validator(const json &, schema_loader = nullptr, format_checker = nullptr);
~json_validator();
json_validator &operator=(json_validator &&);
diff --git a/src/json-validator.cpp b/src/json-validator.cpp
index 8f6526b..b28d326 100644
--- a/src/json-validator.cpp
+++ b/src/json-validator.cpp
@@ -1123,6 +1123,12 @@ json_validator::json_validator(schema_loader loader,
{
}
+json_validator::json_validator(const json &schema, schema_loader loader, format_checker format)
+ : json_validator(loader, format)
+{
+ set_root_schema(schema);
+}
+
// move constructor, destructor and move assignment operator can be defaulted here
// where root_schema is a complete type
json_validator::json_validator(json_validator &&) = default;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b0ef6f5..5c0d805 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -30,3 +30,7 @@ add_test(NAME errors COMMAND errors)
add_executable(issue-70 issue-70.cpp)
target_link_libraries(issue-70 json-schema-validator)
add_test(NAME issue-70 COMMAND issue-70)
+
+add_executable(issue-70-root-schema-constructor issue-70-root-schema-constructor.cpp)
+target_link_libraries(issue-70-root-schema-constructor json-schema-validator)
+add_test(NAME issue-70-root-schema-constructor COMMAND issue-70-root-schema-constructor)
diff --git a/test/issue-70-root-schema-constructor.cpp b/test/issue-70-root-schema-constructor.cpp
new file mode 100644
index 0000000..02dc94f
--- /dev/null
+++ b/test/issue-70-root-schema-constructor.cpp
@@ -0,0 +1,123 @@
+#include
+
+#include
+
+static int error_count;
+
+#define EXPECT_EQ(a, b) \
+ do { \
+ if (a != b) { \
+ std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; \
+ error_count++; \
+ } \
+ } while (0)
+
+using nlohmann::json;
+using nlohmann::json_schema::json_validator;
+
+namespace
+{
+
+// The schema is defined based upon a string literal
+static json person_schema = R"(
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "A person",
+ "properties": {
+ "name": {
+ "description": "Name",
+ "type": "string"
+ },
+ "age": {
+ "description": "Age of the person",
+ "type": "number",
+ "minimum": 2,
+ "maximum": 200
+ },
+ "phones": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
+ }
+ },
+ "required": [
+ "name",
+ "age"
+ ],
+ "additionalProperties": false,
+ "type": "object"
+})"_json;
+
+class store_ptr_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_pointers.push_back(ptr);
+ }
+
+public:
+ std::vector failed_pointers;
+
+ void reset() override
+ {
+ nlohmann::json_schema::basic_error_handler::reset();
+ failed_pointers.clear();
+ }
+};
+
+} // namespace
+
+static json_validator validator(person_schema);
+
+int main(void)
+{
+ store_ptr_err_handler err;
+
+ validator.validate({{"age", 42}, {"name", "John"}}, err); // OK
+ EXPECT_EQ(err.failed_pointers.size(), 0);
+ err.reset();
+
+ validator.validate({{"age", 42}}, err); // no name
+
+ EXPECT_EQ(err.failed_pointers.size(), 1);
+ EXPECT_EQ(err.failed_pointers[0].to_string(), "");
+ err.reset();
+
+ validator.validate({{"street", "Boulevard"}}, err); // no name and no age
+ EXPECT_EQ(err.failed_pointers.size(), 3);
+ EXPECT_EQ(err.failed_pointers[0].to_string(), "");
+ EXPECT_EQ(err.failed_pointers[1].to_string(), "");
+ EXPECT_EQ(err.failed_pointers[2].to_string(), "");
+ err.reset();
+
+ validator.validate({{"age", 42}, {"name", 12}}, err); // name must be a string
+ EXPECT_EQ(err.failed_pointers.size(), 1);
+ EXPECT_EQ(err.failed_pointers[0].to_string(), "/name");
+ err.reset();
+
+ validator.validate({
+ {"age", 42},
+ {"name", "John"},
+ {"phones", {1234, "223"}},
+ },
+ err); // name must be a string
+ EXPECT_EQ(err.failed_pointers.size(), 1);
+ EXPECT_EQ(err.failed_pointers[0].to_string(), "/phones/1");
+ err.reset();
+
+ validator.validate({
+ {"age", 42},
+ {"name", "John"},
+ {"phones", {0}},
+ {"post-code", 12345},
+ },
+ err); // name must be a string
+ EXPECT_EQ(err.failed_pointers.size(), 1);
+ EXPECT_EQ(err.failed_pointers[0].to_string(), "");
+ err.reset();
+
+ return error_count;
+}