|
|
@@ -67,6 +67,17 @@ private:
|
|
|
mutable StoreResults tracking_ = StoreResults::ForInvalid;
|
|
|
|
|
|
public:
|
|
|
+ /**
|
|
|
+ * @brief Construct a new ValidationVisitor
|
|
|
+ *
|
|
|
+ * @param json The JSON document instance being validated
|
|
|
+ * @param schema The parsed JSON Schema
|
|
|
+ * @param cfg General configuration settings for how the run is executed
|
|
|
+ * @param regex_cache A cache of string regular expressions to compiled
|
|
|
+ * regular expressions
|
|
|
+ * @param[optional] result A cache of result/annotation info for the user to
|
|
|
+ * receive a detailed summary of why a document is supported/unsupported.
|
|
|
+ */
|
|
|
ValidationVisitor(A const & json, schema::Node const & schema, ValidationConfig const & cfg,
|
|
|
std::unordered_map<std::string, RE> & regex_cache, ValidationResult * result)
|
|
|
: document_(json), schema_(&schema), result_(result), cfg_(cfg), regex_cache_(regex_cache) {}
|
|
|
@@ -554,11 +565,21 @@ public:
|
|
|
return rval;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief The main entry point into the validator. Validates the provided
|
|
|
+ * document according to the schema.
|
|
|
+ */
|
|
|
Status validate() {
|
|
|
+ // Step 1) Check if this is an always-false schema. Sometimes, this will
|
|
|
+ // have a custom message.
|
|
|
if (std::optional<std::string> const & reject = schema_->rejects_all()) {
|
|
|
if (should_annotate(Status::Reject)) {
|
|
|
+ // This will only be run if we are interested in why something is
|
|
|
+ // rejected. For example - `{ "not": false }` doesn't produce a
|
|
|
+ // meaningful annotation...
|
|
|
result_->error(where_, schema_path_, "", *reject);
|
|
|
}
|
|
|
+ // ...We do always record the result if a result object is present.
|
|
|
(result_ ? result_->valid(where_, schema_path_, false) : void());
|
|
|
return Status::Reject;
|
|
|
}
|
|
|
@@ -569,12 +590,18 @@ public:
|
|
|
return Status::Accept;
|
|
|
}
|
|
|
|
|
|
+ // Begin tracking evaluations for unevaluated* keywords. The annotation
|
|
|
+ // object is passed down from parent visitor to child visitor to allow all
|
|
|
+ // schemas to mark whether they visited a certain item or property.
|
|
|
VisitedAnnotation annotate;
|
|
|
if (schema_->requires_result_context() and not visited_) {
|
|
|
visited_ = &annotate;
|
|
|
}
|
|
|
|
|
|
Status rval = Status::Noop;
|
|
|
+ // Before Draft2019_09, reference schemas could not coexist with other
|
|
|
+ // constraints. This is enforced in the parsing of the schema, rather than
|
|
|
+ // during validation {@see jvalidate::schema::Node::construct}.
|
|
|
if (std::optional<schema::Node const *> ref = schema_->reference_schema()) {
|
|
|
rval = validate_subschema(*ref, "$ref");
|
|
|
}
|
|
|
@@ -586,6 +613,8 @@ public:
|
|
|
rval &= p_constraint->accept(*this);
|
|
|
}
|
|
|
|
|
|
+ // Post Constraints represent the unevaluatedItems and unevaluatedProperties
|
|
|
+ // keywords.
|
|
|
for (auto const & [key, p_constraint] : schema_->post_constraints()) {
|
|
|
BREAK_EARLY_IF_NO_RESULT_TREE();
|
|
|
schema_path_ = current_schema / key;
|
|
|
@@ -651,6 +680,17 @@ private:
|
|
|
return (should_annotate(stat) ? error(args...) : void(), stat);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Walking function for entering a subschema.
|
|
|
+ *
|
|
|
+ * @param subschema The "subschema" being validated. This is either another
|
|
|
+ * schema object (jvalidate::schema::Node), or a constraint.
|
|
|
+ * @param keys... The path to this subschema, relative to the current schema
|
|
|
+ * evaluation.
|
|
|
+ *
|
|
|
+ * @return The status of validating the current instance against the
|
|
|
+ * subschema.
|
|
|
+ */
|
|
|
template <typename... K>
|
|
|
Status validate_subschema(constraint::SubConstraint const & subschema, K const &... keys) const {
|
|
|
if (schema::Node const * const * ppschema = std::get_if<0>(&subschema)) {
|
|
|
@@ -660,6 +700,17 @@ private:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Walking function for entering a subschema. Creates a new validation
|
|
|
+ * visitor in order to continue evaluation.
|
|
|
+ *
|
|
|
+ * @param subschema The subschema being validated.
|
|
|
+ * @param keys... The path to this subschema, relative to the current schema
|
|
|
+ * evaluation.
|
|
|
+ *
|
|
|
+ * @return The status of validating the current instance against the
|
|
|
+ * subschema.
|
|
|
+ */
|
|
|
template <typename... K>
|
|
|
Status validate_subschema(schema::Node const * subschema, K const &... keys) const {
|
|
|
VisitedAnnotation annotate;
|
|
|
@@ -678,6 +729,17 @@ private:
|
|
|
return rval;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Walking function for entering a subschema and child document.
|
|
|
+ * Creates a new validation visitor in order to continue evaluation.
|
|
|
+ *
|
|
|
+ * @param subschema The subschema being validated.
|
|
|
+ * @param document The child document being evaluated.
|
|
|
+ * @param key The path to this document instance.
|
|
|
+ *
|
|
|
+ * @return The status of validating the current instance against the
|
|
|
+ * subschema.
|
|
|
+ */
|
|
|
template <typename K>
|
|
|
Status validate_subschema_on(schema::Node const * subschema, A const & document,
|
|
|
K const & key) const {
|