Implement propertyNames constraint

This commit is contained in:
Tristan Penman 2019-10-10 13:23:42 +11:00
parent dcddea604d
commit 6287656e2b
5 changed files with 88 additions and 0 deletions

View File

@ -1016,6 +1016,30 @@ private:
const Subschema *additionalProperties;
};
class PropertyNamesConstraint: public BasicConstraint<PropertyNamesConstraint>
{
public:
PropertyNamesConstraint()
: subschema(NULL) { }
PropertyNamesConstraint(CustomAlloc allocFn, CustomFree freeFn)
: BasicConstraint(allocFn, freeFn),
subschema(NULL) { }
const Subschema * getSubschema() const
{
return subschema;
}
void setSubschema(const Subschema *subschema)
{
this->subschema = subschema;
}
private:
const Subschema *subschema;
};
/**
* @brief Represents a 'required' constraint
*/

View File

@ -26,6 +26,7 @@ class OneOfConstraint;
class PatternConstraint;
class PolyConstraint;
class PropertiesConstraint;
class PropertyNamesConstraint;
class RequiredConstraint;
class SingularItemsConstraint;
class TypeConstraint;
@ -61,6 +62,7 @@ protected:
typedef constraints::PatternConstraint PatternConstraint;
typedef constraints::PolyConstraint PolyConstraint;
typedef constraints::PropertiesConstraint PropertiesConstraint;
typedef constraints::PropertyNamesConstraint PropertyNamesConstraint;
typedef constraints::RequiredConstraint RequiredConstraint;
typedef constraints::SingularItemsConstraint SingularItemsConstraint;
typedef constraints::TypeConstraint TypeConstraint;
@ -91,6 +93,7 @@ public:
virtual bool visit(const PatternConstraint &) = 0;
virtual bool visit(const PolyConstraint &) = 0;
virtual bool visit(const PropertiesConstraint &) = 0;
virtual bool visit(const PropertyNamesConstraint &) = 0;
virtual bool visit(const RequiredConstraint &) = 0;
virtual bool visit(const SingularItemsConstraint &) = 0;
virtual bool visit(const TypeConstraint &) = 0;

View File

@ -910,6 +910,17 @@ private:
}
}
if ((itr = object.find("propertyNames")) != object.end()) {
if (version == kDraft7) {
rootSchema.addConstraintToSubschema(
makePropertyNamesConstraint(rootSchema, rootNode, itr->second, updatedScope,
nodePath, fetchDoc, docCache, schemaCache),
&subschema);
} else {
throw std::runtime_error("Not supported");
}
}
if ((itr = object.find("required")) != object.end()) {
if (version == kDraft3) {
if (parentSubschema && ownName) {
@ -2182,6 +2193,26 @@ private:
return constraint;
}
template<typename AdapterType>
constraints::PropertyNamesConstraint makePropertyNamesConstraint(
Schema &rootSchema,
const AdapterType &rootNode,
const AdapterType &currentNode,
const opt::optional<std::string> currentScope,
const std::string &nodePath,
const typename FunctionPtrs<AdapterType>::FetchDoc fetchDoc,
typename DocumentCache<AdapterType>::Type &docCache,
SchemaCache &schemaCache)
{
const Subschema *subschema = makeOrReuseSchema<AdapterType>(rootSchema, rootNode,
currentNode, currentScope, nodePath, fetchDoc, nullptr, nullptr, docCache,
schemaCache);
constraints::PropertyNamesConstraint constraint;
constraint.setSubschema(subschema);
return constraint;
}
/**
* @brief Make a new RequiredConstraint.
*

View File

@ -4,6 +4,7 @@
#include <string>
#include <regex>
#include <valijson/adapters/std_string_adapter.hpp>
#include <valijson/constraints/concrete_constraints.hpp>
#include <valijson/constraints/constraint_visitor.hpp>
#include <valijson/validation_results.hpp>
@ -1000,6 +1001,30 @@ public:
return validated;
}
/**
* @brief Validate a value against a PropertyNamesConstraint
*
* @param constraint Constraint that the target must validate against
*
* @return \c true if validation succeeds; \c false otherwise
*/
virtual bool visit(const PropertyNamesConstraint &constraint)
{
if ((strictTypes && !target.isObject()) || !target.maybeObject()) {
return true;
}
for (const typename AdapterType::ObjectMember m : target.asObject()) {
adapters::StdStringAdapter stringAdapter(m.first);
ValidationVisitor<adapters::StdStringAdapter> validator(stringAdapter, context, strictTypes, nullptr);
if (!validator.validateSchema(*constraint.getSubschema())) {
return false;
}
}
return true;
}
/**
* @brief Validate a value against a RequiredConstraint
*

View File

@ -553,6 +553,11 @@ TEST_F(TestValidator, Draft7_Properties)
processDraft7TestFile(TEST_SUITE_DIR "draft7/properties.json");
}
TEST_F(TestValidator, Draft7_PropertyNames)
{
processDraft7TestFile(TEST_SUITE_DIR "draft7/propertyNames.json");
}
// TODO: broken ref
// TODO: broken refRemote