| 1053 | std::shared_ptr<schema> propertyNames_; |
| 1054 | |
| 1055 | void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override |
| 1056 | { |
| 1057 | if (maxProperties_.first && instance.size() > maxProperties_.second) |
| 1058 | e.error(ptr, instance, "too many properties"); |
| 1059 | |
| 1060 | if (minProperties_.first && instance.size() < minProperties_.second) |
| 1061 | e.error(ptr, instance, "too few properties"); |
| 1062 | |
| 1063 | for (auto &r : required_) |
| 1064 | if (instance.find(r) == instance.end()) |
| 1065 | e.error(ptr, instance, "required property '" + r + "' not found in object"); |
| 1066 | |
| 1067 | // for each property in instance |
| 1068 | for (auto &p : instance.items()) { |
| 1069 | if (propertyNames_) |
| 1070 | propertyNames_->validate(ptr, p.key(), patch, e); |
| 1071 | |
| 1072 | bool a_prop_or_pattern_matched = false; |
| 1073 | auto schema_p = properties_.find(p.key()); |
| 1074 | // check if it is in "properties" |
| 1075 | if (schema_p != properties_.end()) { |
| 1076 | a_prop_or_pattern_matched = true; |
| 1077 | schema_p->second->validate(ptr / p.key(), p.value(), patch, e); |
| 1078 | } |
| 1079 | |
| 1080 | #ifndef NO_STD_REGEX |
| 1081 | // check all matching patternProperties |
| 1082 | for (auto &schema_pp : patternProperties_) |
| 1083 | if (REGEX_NAMESPACE::regex_search(p.key(), schema_pp.first)) { |
| 1084 | a_prop_or_pattern_matched = true; |
| 1085 | schema_pp.second->validate(ptr / p.key(), p.value(), patch, e); |
| 1086 | } |
| 1087 | #endif |
| 1088 | |
| 1089 | // check additionalProperties as a last resort |
| 1090 | if (!a_prop_or_pattern_matched && additionalProperties_) { |
| 1091 | first_error_handler additional_prop_err; |
| 1092 | additionalProperties_->validate(ptr / p.key(), p.value(), patch, additional_prop_err); |
| 1093 | if (additional_prop_err) |
| 1094 | e.error(ptr, instance, "validation failed for additional property '" + p.key() + "': " + additional_prop_err.message_); |
| 1095 | } |
| 1096 | } |
| 1097 | |
| 1098 | // reverse search |
| 1099 | for (auto const &prop : properties_) { |
| 1100 | const auto finding = instance.find(prop.first); |
| 1101 | if (instance.end() == finding) { // if the prop is not in the instance |
| 1102 | const auto &default_value = prop.second->default_value(ptr, instance, e); |
| 1103 | if (!default_value.is_null()) { // if default value is available |
| 1104 | patch.add((ptr / prop.first), default_value); |
| 1105 | } |
| 1106 | } |
| 1107 | } |
| 1108 | |
| 1109 | for (auto &dep : dependencies_) { |
| 1110 | auto prop = instance.find(dep.first); |
| 1111 | if (prop != instance.end()) // if dependency-property is present in instance |
| 1112 | dep.second->validate(ptr / dep.first, instance, patch, e); // validate |