From 1d055261b4144dbf86b2658437015b15d4dd9bff Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 4 Sep 2022 00:32:56 +0100 Subject: initial --- include/jsoncons_ext/jsonschema/subschema.hpp | 144 ++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 include/jsoncons_ext/jsonschema/subschema.hpp (limited to 'include/jsoncons_ext/jsonschema/subschema.hpp') diff --git a/include/jsoncons_ext/jsonschema/subschema.hpp b/include/jsoncons_ext/jsonschema/subschema.hpp new file mode 100644 index 0000000..cbe0af4 --- /dev/null +++ b/include/jsoncons_ext/jsonschema/subschema.hpp @@ -0,0 +1,144 @@ +// Copyright 2020 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_JSONSCHEMA_SUBSCHEMA_HPP +#define JSONCONS_JSONSCHEMA_SUBSCHEMA_HPP + +#include +#include +#include +#include +#include +#include + +namespace jsoncons { +namespace jsonschema { + + // Interface for validation error handlers + class error_reporter + { + bool fail_early_; + std::size_t error_count_; + public: + error_reporter(bool fail_early = false) + : fail_early_(fail_early), error_count_(0) + { + } + + virtual ~error_reporter() = default; + + void error(const validation_output& o) + { + ++error_count_; + do_error(o); + } + + std::size_t error_count() const + { + return error_count_; + } + + bool fail_early() const + { + return fail_early_; + } + + private: + virtual void do_error(const validation_output& /* e */) = 0; + }; + + template + class keyword_validator + { + std::string absolute_keyword_location_; + public: + using self_pointer = keyword_validator*; + + keyword_validator(const std::string& absolute_keyword_location) + : absolute_keyword_location_(absolute_keyword_location) + { + } + + keyword_validator(const keyword_validator&) = delete; + keyword_validator(keyword_validator&&) = default; + keyword_validator& operator=(const keyword_validator&) = delete; + keyword_validator& operator=(keyword_validator&&) = default; + + virtual ~keyword_validator() = default; + + const std::string& absolute_keyword_location() const + { + return absolute_keyword_location_; + } + + void validate(const Json& instance, + const jsonpointer::json_pointer& instance_location, + error_reporter& reporter, + Json& patch) const + { + do_validate(instance, + instance_location, + reporter, + patch); + } + + virtual jsoncons::optional get_default_value(const jsonpointer::json_pointer&, const Json&, error_reporter&) const + { + return jsoncons::optional(); + } + + private: + virtual void do_validate(const Json& instance, + const jsonpointer::json_pointer& instance_location, + error_reporter& reporter, + Json& patch) const = 0; + }; + + template + std::vector update_uris(const Json& schema, + const std::vector& uris, + const std::vector& keys) + { + // Exclude uri's that are not plain name identifiers + std::vector new_uris; + for (const auto& uri : uris) + { + if (!uri.has_identifier()) + new_uris.push_back(uri); + } + + // Append the keys for this sub-schema to the uri's + for (const auto& key : keys) + { + for (auto& uri : new_uris) + { + auto new_u = uri.append(key); + uri = schema_location(new_u); + } + } + if (schema.type() == json_type::object_value) + { + auto it = schema.find("$id"); // If $id is found, this schema can be referenced by the id + if (it != schema.object_range().end()) + { + std::string id = it->value().template as(); + // Add it to the list if it is not already there + if (std::find(new_uris.begin(), new_uris.end(), id) == new_uris.end()) + { + schema_location relative(id); + schema_location new_uri = relative.resolve(new_uris.back()); + new_uris.emplace_back(new_uri); + } + } + } + + return new_uris; + } + +} // namespace jsonschema +} // namespace jsoncons + +#endif // JSONCONS_JSONSCHEMA_RULE_HPP -- cgit v1.2.3