|
@@ -67,12 +67,16 @@ private:
|
|
|
{"dependencies", &Self::dependencies},
|
|
{"dependencies", &Self::dependencies},
|
|
|
{"dependentRequired", {schema::Version::Draft2019_09, &Self::dependentRequired}},
|
|
{"dependentRequired", {schema::Version::Draft2019_09, &Self::dependentRequired}},
|
|
|
{"dependentSchemas", {schema::Version::Draft2019_09, &Self::dependentSchemas}},
|
|
{"dependentSchemas", {schema::Version::Draft2019_09, &Self::dependentSchemas}},
|
|
|
|
|
+ {"disallow",
|
|
|
|
|
+ {{schema::Version::Earliest, &Self::disallowDraft3}, {schema::Version::Draft04, Removed}}},
|
|
|
{"divisibleBy",
|
|
{"divisibleBy",
|
|
|
{{schema::Version::Earliest, &Self::multipleOf}, {schema::Version::Draft04, Removed}}},
|
|
{{schema::Version::Earliest, &Self::multipleOf}, {schema::Version::Draft04, Removed}}},
|
|
|
{"else", {{schema::Version::Draft07, Keyword}}},
|
|
{"else", {{schema::Version::Draft07, Keyword}}},
|
|
|
{"enum", &Self::isInEnumuration},
|
|
{"enum", &Self::isInEnumuration},
|
|
|
{"exclusiveMaximum", {schema::Version::Draft06, &Self::exclusiveMaximum}},
|
|
{"exclusiveMaximum", {schema::Version::Draft06, &Self::exclusiveMaximum}},
|
|
|
{"exclusiveMinimum", {schema::Version::Draft06, &Self::exclusiveMinimum}},
|
|
{"exclusiveMinimum", {schema::Version::Draft06, &Self::exclusiveMinimum}},
|
|
|
|
|
+ {"extends",
|
|
|
|
|
+ {{schema::Version::Earliest, &Self::extendsDraft3}, {schema::Version::Draft04, Removed}}},
|
|
|
{"format", &Self::format},
|
|
{"format", &Self::format},
|
|
|
{"if", {schema::Version::Draft07, &Self::ifThenElse}},
|
|
{"if", {schema::Version::Draft07, &Self::ifThenElse}},
|
|
|
{"items",
|
|
{"items",
|
|
@@ -92,11 +96,14 @@ private:
|
|
|
{"pattern", &Self::pattern},
|
|
{"pattern", &Self::pattern},
|
|
|
{"patternProperties", &Self::patternProperties},
|
|
{"patternProperties", &Self::patternProperties},
|
|
|
{"prefixItems", {schema::Version::Draft2020_12, &Self::prefixItems}},
|
|
{"prefixItems", {schema::Version::Draft2020_12, &Self::prefixItems}},
|
|
|
- {"properties", &Self::properties},
|
|
|
|
|
|
|
+ {"properties",
|
|
|
|
|
+ {{schema::Version::Earliest, &Self::propertiesDraft3},
|
|
|
|
|
+ {schema::Version::Draft04, &Self::properties}}},
|
|
|
{"propertyNames", {schema::Version::Draft06, &Self::propertyNames}},
|
|
{"propertyNames", {schema::Version::Draft06, &Self::propertyNames}},
|
|
|
{"required", {schema::Version::Draft04, &Self::required}},
|
|
{"required", {schema::Version::Draft04, &Self::required}},
|
|
|
{"then", {schema::Version::Draft07, Keyword}},
|
|
{"then", {schema::Version::Draft07, Keyword}},
|
|
|
- {"type", &Self::type},
|
|
|
|
|
|
|
+ {"type",
|
|
|
|
|
+ {{schema::Version::Earliest, &Self::typeDraft3}, {schema::Version::Draft04, &Self::type}}},
|
|
|
{"unevaluatedItems", {schema::Version::Draft2019_09, &Self::unevaluatedItems}},
|
|
{"unevaluatedItems", {schema::Version::Draft2019_09, &Self::unevaluatedItems}},
|
|
|
{"unevaluatedProperties", {schema::Version::Draft2019_09, &Self::unevaluatedProperties}},
|
|
{"unevaluatedProperties", {schema::Version::Draft2019_09, &Self::unevaluatedProperties}},
|
|
|
{"uniqueItems", &Self::uniqueItems},
|
|
{"uniqueItems", &Self::uniqueItems},
|
|
@@ -158,6 +165,73 @@ public:
|
|
|
return std::make_unique<constraint::TypeConstraint>(types);
|
|
return std::make_unique<constraint::TypeConstraint>(types);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ static pConstraint typeDraft3(detail::ParserContext<A> const & context) {
|
|
|
|
|
+ static std::unordered_map<std::string_view, adapter::Type> const s_type_names{
|
|
|
|
|
+ {"null", adapter::Type::Null}, {"boolean", adapter::Type::Boolean},
|
|
|
|
|
+ {"integer", adapter::Type::Integer}, {"number", adapter::Type::Number},
|
|
|
|
|
+ {"string", adapter::Type::String}, {"array", adapter::Type::Array},
|
|
|
|
|
+ {"object", adapter::Type::Object},
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ auto to_type = [](std::string_view type) {
|
|
|
|
|
+ EXPECT_M(s_type_names.contains(type), "Unknown type " << type);
|
|
|
|
|
+ return s_type_names.at(type);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ adapter::Type const type = context.schema.type();
|
|
|
|
|
+ if (type == adapter::Type::String) {
|
|
|
|
|
+ if (context.schema.as_string() == "any") {
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+ }
|
|
|
|
|
+ return std::make_unique<constraint::TypeConstraint>(to_type(context.schema.as_string()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ EXPECT(type == adapter::Type::Array);
|
|
|
|
|
+ std::vector<schema::Node const *> children;
|
|
|
|
|
+
|
|
|
|
|
+ std::set<adapter::Type> types;
|
|
|
|
|
+ size_t index = 0;
|
|
|
|
|
+ for (auto subschema : context.schema.as_array()) {
|
|
|
|
|
+ if (subschema.type() != adapter::Type::String) {
|
|
|
|
|
+ children.push_back(context.child(subschema, index).node());
|
|
|
|
|
+ } else if (subschema.as_string() == "any") {
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ types.insert(to_type(subschema.as_string()));
|
|
|
|
|
+ }
|
|
|
|
|
+ ++index;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return constraint::PolyConstraint::AnyOf(
|
|
|
|
|
+ std::make_unique<constraint::TypeConstraint>(types),
|
|
|
|
|
+ std::make_unique<constraint::AnyOfConstraint>(children));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static pConstraint disallowDraft3(detail::ParserContext<A> const & context) {
|
|
|
|
|
+ return constraint::PolyConstraint::Not(typeDraft3(context));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static pConstraint extendsDraft3(detail::ParserContext<A> const & context) {
|
|
|
|
|
+ std::vector<schema::Node const *> children;
|
|
|
|
|
+ switch (context.schema.type()) {
|
|
|
|
|
+ case adapter::Type::Object:
|
|
|
|
|
+ children.push_back(context.node());
|
|
|
|
|
+ break;
|
|
|
|
|
+ case adapter::Type::Array: {
|
|
|
|
|
+ size_t index = 0;
|
|
|
|
|
+ for (auto const & subschema : context.schema.as_array()) {
|
|
|
|
|
+ children.push_back(context.child(subschema, index).node());
|
|
|
|
|
+ ++index;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ default:
|
|
|
|
|
+ JVALIDATE_THROW(std::runtime_error, "extends must be a schema of array-of-schemas");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return std::make_unique<constraint::AllOfConstraint>(children);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
static pConstraint ifThenElse(detail::ParserContext<A> const & context) {
|
|
static pConstraint ifThenElse(detail::ParserContext<A> const & context) {
|
|
|
schema::Node const * then_ = context.fixed_schema(true);
|
|
schema::Node const * then_ = context.fixed_schema(true);
|
|
|
if (context.parent->contains("then")) {
|
|
if (context.parent->contains("then")) {
|
|
@@ -431,6 +505,25 @@ public:
|
|
|
return std::make_unique<constraint::PropertiesConstraint>(rval);
|
|
return std::make_unique<constraint::PropertiesConstraint>(rval);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ static pConstraint propertiesDraft3(detail::ParserContext<A> const & context) {
|
|
|
|
|
+ EXPECT(context.schema.type() == adapter::Type::Object);
|
|
|
|
|
+
|
|
|
|
|
+ std::unordered_set<std::string> required;
|
|
|
|
|
+ for (auto [prop, subschema] : context.schema.as_object()) {
|
|
|
|
|
+ EXPECT(subschema.type() == adapter::Type::Object);
|
|
|
|
|
+ if (auto sub = subschema.as_object();
|
|
|
|
|
+ sub.contains("required") && sub["required"].as_boolean()) {
|
|
|
|
|
+ required.insert(prop);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (required.empty()) {
|
|
|
|
|
+ return properties(context);
|
|
|
|
|
+ }
|
|
|
|
|
+ return constraint::PolyConstraint::AllOf(
|
|
|
|
|
+ properties(context), std::make_unique<constraint::RequiredConstraint>(std::move(required)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
static auto propertyNames(detail::ParserContext<A> const & context) {
|
|
static auto propertyNames(detail::ParserContext<A> const & context) {
|
|
|
return std::make_unique<constraint::PropertyNamesConstraint>(context.node());
|
|
return std::make_unique<constraint::PropertyNamesConstraint>(context.node());
|
|
|
}
|
|
}
|
|
@@ -475,6 +568,9 @@ public:
|
|
|
EXPECT(key.type() == adapter::Type::String);
|
|
EXPECT(key.type() == adapter::Type::String);
|
|
|
required[prop].insert(key.as_string());
|
|
required[prop].insert(key.as_string());
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if (context.vocab->version() <= schema::Version::Draft03 &&
|
|
|
|
|
+ subschema.type() == adapter::Type::String) {
|
|
|
|
|
+ required[prop].insert(subschema.as_string());
|
|
|
} else {
|
|
} else {
|
|
|
schemas.emplace(prop, context.child(subschema, prop).node());
|
|
schemas.emplace(prop, context.child(subschema, prop).node());
|
|
|
}
|
|
}
|