Commit d5c2f2ec authored by miloyip's avatar miloyip

Add patternProperties in schema

parent 8366bb89
......@@ -259,6 +259,10 @@ public:
BaseSchema<Encoding>(value),
properties_(),
additionalPropertySchema_(),
#if RAPIDJSON_SCHEMA_HAS_REGEX
patternProperties_(),
patternPropertyCount_(),
#endif
propertyCount_(),
requiredCount_(),
minProperties_(),
......@@ -279,6 +283,31 @@ public:
}
}
#if RAPIDJSON_SCHEMA_HAS_REGEX
typename ValueType::ConstMemberIterator patternPropretiesItr = value.FindMember("patternProperties");
if (patternPropretiesItr != value.MemberEnd()) {
const ValueType& patternProperties = patternPropretiesItr->value;
patternProperties_ = new PatternProperty[patternProperties.MemberCount()];
patternPropertyCount_ = 0;
for (typename ValueType::ConstMemberIterator propertyItr = patternProperties.MemberBegin(); propertyItr != patternProperties.MemberEnd(); ++propertyItr) {
#if RAPIDJSON_SCHEMA_USE_STDREGEX
try {
patternProperties_[patternPropertyCount_].pattern = new std::basic_regex<Ch>(
propertyItr->name.GetString(),
std::size_t(propertyItr->name.GetStringLength()),
std::regex_constants::ECMAScript);
}
catch (const std::regex_error&) {
// Error
}
#endif
patternProperties_[patternPropertyCount_].schema = CreateSchema<Encoding>(propertyItr->value); // TODO: Check error
patternPropertyCount_++;
}
}
#endif
// Establish required after properties
typename ValueType::ConstMemberIterator requiredItr = value.FindMember("required");
if (requiredItr != value.MemberEnd()) {
......@@ -372,6 +401,9 @@ public:
~ObjectSchema() {
delete [] properties_;
delete additionalPropertySchema_;
#if RAPIDJSON_SCHEMA_HAS_REGEX
delete [] patternProperties_;
#endif
}
virtual SchemaType GetSchemaType() const { return kObjectSchemaType; }
......@@ -408,6 +440,22 @@ public:
return true;
}
#if RAPIDJSON_SCHEMA_HAS_REGEX
if (patternProperties_) {
for (SizeType i = 0; i < patternPropertyCount_; i++) {
#if RAPIDJSON_SCHEMA_USE_STDREGEX
if (patternProperties_[i].pattern) {
std::match_results<const Ch*> r;
if (std::regex_search(str, str + len, r, *patternProperties_[i].pattern)) {
context.valueSchema = patternProperties_[i].schema;
return true;
}
}
#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
}
}
#endif
if (additionalPropertySchema_) {
context.valueSchema = additionalPropertySchema_;
return true;
......@@ -477,9 +525,28 @@ private:
bool required;
};
#if RAPIDJSON_SCHEMA_HAS_REGEX
struct PatternProperty {
PatternProperty() : schema(), pattern() {}
~PatternProperty() {
delete schema;
delete pattern;
}
BaseSchema<Encoding>* schema;
#if RAPIDJSON_SCHEMA_USE_STDREGEX
std::basic_regex<Ch>* pattern;
#endif
};
#endif
TypelessSchema<Encoding> typeless_;
Property* properties_;
BaseSchema<Encoding>* additionalPropertySchema_;
#if RAPIDJSON_SCHEMA_HAS_REGEX
PatternProperty* patternProperties_;
SizeType patternPropertyCount_;
#endif
SizeType propertyCount_;
SizeType requiredCount_;
SizeType minProperties_;
......@@ -689,7 +756,7 @@ public:
if (pattern_) {
#if RAPIDJSON_SCHEMA_USE_STDREGEX
std::match_results<const Ch*> r;
if (!std::regex_match(str, str + length, r, *pattern_))
if (!std::regex_search(str, str + length, r, *pattern_))
return false;
#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
}
......
......@@ -314,6 +314,46 @@ TEST(SchemaValidator, Object_PropertyDependencies) {
VALIDATE(s, "{ \"name\": \"John Doe\", \"billing_address\": \"555 Debtor's Lane\" }", true);
}
TEST(SchemaValidator, Object_PatternProperties) {
Document sd;
sd.Parse(
"{"
" \"type\": \"object\","
" \"patternProperties\": {"
" \"^S_\": { \"type\": \"string\" },"
" \"^I_\": { \"type\": \"integer\" }"
" }"
"}");
Schema s(sd);
VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true);
VALIDATE(s, "{ \"I_0\": 42 }", true);
VALIDATE(s, "{ \"S_0\": 42 }", false);
VALIDATE(s, "{ \"I_42\": \"This is a string\" }", false);
VALIDATE(s, "{ \"keyword\": \"value\" }", true);
}
TEST(SchemaValidator, Object_PatternProperties_AdditionalProperties) {
Document sd;
sd.Parse(
"{"
" \"type\": \"object\","
" \"properties\": {"
" \"builtin\": { \"type\": \"number\" }"
" },"
" \"patternProperties\": {"
" \"^S_\": { \"type\": \"string\" },"
" \"^I_\": { \"type\": \"integer\" }"
" },"
" \"additionalProperties\": { \"type\": \"string\" }"
"}");
Schema s(sd);
VALIDATE(s, "{ \"builtin\": 42 }", true);
VALIDATE(s, "{ \"keyword\": \"value\" }", true);
VALIDATE(s, "{ \"keyword\": 42 }", false);
}
TEST(SchemaValidator, Array) {
Document sd;
sd.Parse("{\"type\":\"array\"}");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment