mirror of
https://github.com/tristanpenman/valijson.git
synced 2025-03-02 20:30:11 +01:00
Initial support for 'if', 'then' and 'else' subschemas
This commit is contained in:
parent
dac4cff42f
commit
925ff8ff68
@ -118,7 +118,51 @@ private:
|
||||
class ConditionalConstraint: public BasicConstraint<ConditionalConstraint>
|
||||
{
|
||||
public:
|
||||
ConditionalConstraint() { }
|
||||
ConditionalConstraint()
|
||||
: ifSubschema(NULL),
|
||||
thenSubschema(NULL),
|
||||
elseSubschema(NULL) { }
|
||||
|
||||
ConditionalConstraint(CustomAlloc allocFn, CustomFree freeFn)
|
||||
: BasicConstraint(allocFn, freeFn),
|
||||
ifSubschema(NULL),
|
||||
thenSubschema(NULL),
|
||||
elseSubschema(NULL) { }
|
||||
|
||||
const Subschema * getIfSubschema() const
|
||||
{
|
||||
return ifSubschema;
|
||||
}
|
||||
|
||||
const Subschema * getThenSubschema() const
|
||||
{
|
||||
return thenSubschema;
|
||||
}
|
||||
|
||||
const Subschema * getElseSubschema() const
|
||||
{
|
||||
return elseSubschema;
|
||||
}
|
||||
|
||||
void setIfSubschema(const Subschema *subschema)
|
||||
{
|
||||
ifSubschema = subschema;
|
||||
}
|
||||
|
||||
void setThenSubschema(const Subschema *subschema)
|
||||
{
|
||||
thenSubschema = subschema;
|
||||
}
|
||||
|
||||
void setElseSubschema(const Subschema *subschema)
|
||||
{
|
||||
elseSubschema = subschema;
|
||||
}
|
||||
|
||||
private:
|
||||
const Subschema *ifSubschema;
|
||||
const Subschema *thenSubschema;
|
||||
const Subschema *elseSubschema;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -37,7 +37,8 @@ public:
|
||||
/// Supported versions of JSON Schema
|
||||
enum Version {
|
||||
kDraft3, ///< @deprecated JSON Schema v3 has been superseded by v4
|
||||
kDraft4
|
||||
kDraft4,
|
||||
kDraft7
|
||||
};
|
||||
|
||||
/// Version of JSON Schema that should be expected when parsing
|
||||
@ -710,6 +711,25 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const typename AdapterType::Object::const_iterator ifItr = object.find("if");
|
||||
const typename AdapterType::Object::const_iterator thenItr = object.find("then");
|
||||
const typename AdapterType::Object::const_iterator elseItr = object.find("end");
|
||||
|
||||
if (object.end() != ifItr && object.end() != thenItr) {
|
||||
if (version == kDraft7) {
|
||||
rootSchema.addConstraintToSubschema(
|
||||
makeConditionalConstraint(rootSchema, rootNode,
|
||||
ifItr->second, thenItr->second,
|
||||
elseItr == object.end() ? NULL : &elseItr->second,
|
||||
updatedScope, nodePath, fetchDoc, docCache, schemaCache),
|
||||
&subschema);
|
||||
} else {
|
||||
throw std::runtime_error("Not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((itr = object.find("maximum")) != object.end()) {
|
||||
typename AdapterType::Object::const_iterator exclusiveMaximumItr =
|
||||
object.find("exclusiveMaximum");
|
||||
@ -1138,6 +1158,24 @@ private:
|
||||
{
|
||||
constraints::ConditionalConstraint constraint;
|
||||
|
||||
const Subschema *ifSubschema = makeOrReuseSchema<AdapterType>(
|
||||
rootSchema, rootNode, ifNode, currentScope,
|
||||
nodePath, fetchDoc, NULL, NULL, docCache,
|
||||
schemaCache);
|
||||
constraint.setIfSubschema(ifSubschema);
|
||||
|
||||
const Subschema *thenSubschema = makeOrReuseSchema<AdapterType>(
|
||||
rootSchema, rootNode, thenNode, currentScope, nodePath, fetchDoc, NULL, NULL,
|
||||
docCache, schemaCache);
|
||||
constraint.setThenSubschema(thenSubschema);
|
||||
|
||||
if (elseNode) {
|
||||
const Subschema *elseSubschema = makeOrReuseSchema<AdapterType>(
|
||||
rootSchema, rootNode, *elseNode, currentScope, nodePath, fetchDoc, NULL, NULL,
|
||||
docCache, schemaCache);
|
||||
constraint.setElseSubschema(elseSubschema);
|
||||
}
|
||||
|
||||
return constraint;
|
||||
}
|
||||
|
||||
|
@ -158,11 +158,30 @@ public:
|
||||
return numValidated > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validate current node using a set of 'if', 'then' and 'else' subschemas
|
||||
*
|
||||
* A conditional constraint allows a document to validated against one of two additional
|
||||
* subschemas (specified via 'then' or 'else' properties) depending on whether the document
|
||||
* satifies an optional subschema (specified via the 'if' property).
|
||||
*
|
||||
* @param constraint ConditionalConstraint that the current node must validate against
|
||||
*
|
||||
* @return \c true if validation passes; \c false otherwise
|
||||
*/
|
||||
virtual bool visit(const ConditionalConstraint &constraint)
|
||||
{
|
||||
return false;
|
||||
// Create a validator to evaluate the conditional
|
||||
ValidationVisitor ifValidator(target, context, strictTypes, NULL);
|
||||
ValidationVisitor thenElseValidator(target, context, strictTypes, NULL);
|
||||
|
||||
if (ifValidator.validateSchema(*constraint.getIfSubschema())) {
|
||||
return thenElseValidator.validateSchema(*constraint.getThenSubschema());
|
||||
} else {
|
||||
return thenElseValidator.validateSchema(*constraint.getElseSubschema());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Validate current node against a 'dependencies' constraint
|
||||
*
|
||||
|
@ -183,6 +183,11 @@ protected:
|
||||
{
|
||||
return processTestFile(testFile, SchemaParser::kDraft4);
|
||||
}
|
||||
|
||||
void processDraft7TestFile(const std::string &testFile)
|
||||
{
|
||||
return processTestFile(testFile, SchemaParser::kDraft7);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestValidator, Draft3_AdditionalItems)
|
||||
@ -414,3 +419,8 @@ TEST_F(TestValidator, Draft4_UniqueItems)
|
||||
{
|
||||
processDraft4TestFile(TEST_SUITE_DIR "draft4/uniqueItems.json");
|
||||
}
|
||||
|
||||
TEST_F(TestValidator, Draft7_IfThenElse)
|
||||
{
|
||||
processDraft7TestFile(TEST_SUITE_DIR "draft7/if-then-else.json");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user