validator: $ref implemented for local references
But needs more work.
This commit is contained in:
parent
0789403a4b
commit
42a8b00d1d
@ -84,7 +84,7 @@ int main(void)
|
|||||||
There is an application which can be used for testing the validator with the
|
There is an application which can be used for testing the validator with the
|
||||||
[JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
|
[JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
|
||||||
|
|
||||||
Currently **93** of ~**308** tests are still failing, because simply not all keywords and
|
Currently **82** of ~**308** tests are still failing, because simply not all keywords and
|
||||||
their functionalities have been implemented. Some of the missing feature will
|
their functionalities have been implemented. Some of the missing feature will
|
||||||
require a rework. Some will only work with external libraries. (remote references)
|
require a rework. Some will only work with external libraries. (remote references)
|
||||||
|
|
||||||
|
|||||||
@ -14,8 +14,6 @@ int main(void)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_validator validator;
|
|
||||||
|
|
||||||
size_t total_failed = 0,
|
size_t total_failed = 0,
|
||||||
total = 0;
|
total = 0;
|
||||||
|
|
||||||
@ -33,7 +31,9 @@ int main(void)
|
|||||||
bool valid = true;
|
bool valid = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
validator.validate(test_case["data"], schema);
|
json_validator validator;
|
||||||
|
validator.set_schema("#", schema);
|
||||||
|
validator.validate(test_case["data"]);
|
||||||
} catch (const std::out_of_range &e) {
|
} catch (const std::out_of_range &e) {
|
||||||
valid = false;
|
valid = false;
|
||||||
std::cout << " Test Case Exception (out of range): " << e.what() << "\n";
|
std::cout << " Test Case Exception (out of range): " << e.what() << "\n";
|
||||||
@ -62,7 +62,7 @@ int main(void)
|
|||||||
std::cout << "-------------\n";
|
std::cout << "-------------\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << (total - total_failed) << " of " << total << " have succeeded - " << total_failed << " failed\n";
|
std::cout << "Total RESULT: " << (total - total_failed) << " of " << total << " have succeeded - " << total_failed << " failed\n";
|
||||||
|
|
||||||
return total_failed;
|
return total_failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,10 +42,11 @@ int main(int argc, char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_validator validator;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
validator.validate(document, schema);
|
json_validator validator;
|
||||||
|
validator.set_schema("#", schema);
|
||||||
|
validator.validate(document);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
std::cerr << "schema validation failed\n";
|
std::cerr << "schema validation failed\n";
|
||||||
std::cerr << e.what() << "\n";
|
std::cerr << e.what() << "\n";
|
||||||
|
|||||||
@ -314,6 +314,7 @@ class json_validator
|
|||||||
additionalProperties = Object;
|
additionalProperties = Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// patternProperties
|
||||||
json patternProperties = {};
|
json patternProperties = {};
|
||||||
if (schema.find("patternProperties") != schema.end())
|
if (schema.find("patternProperties") != schema.end())
|
||||||
patternProperties = schema["patternProperties"];
|
patternProperties = schema["patternProperties"];
|
||||||
@ -400,57 +401,109 @@ class json_validator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
void validate(json &instance, const json &schema_, const std::string &name)
|
||||||
void validate(json &instance, const json &schema, const std::string &name = "root")
|
|
||||||
{
|
{
|
||||||
not_yet_implemented(schema, "allOf", "all");
|
not_yet_implemented(schema_, "allOf", "all");
|
||||||
not_yet_implemented(schema, "anyOf", "all");
|
not_yet_implemented(schema_, "anyOf", "all");
|
||||||
not_yet_implemented(schema, "oneOf", "all");
|
not_yet_implemented(schema_, "oneOf", "all");
|
||||||
not_yet_implemented(schema, "not", "all");
|
not_yet_implemented(schema_, "not", "all");
|
||||||
not_yet_implemented(schema, "definitions", "all");
|
|
||||||
not_yet_implemented(schema, "$ref", "all");
|
|
||||||
|
|
||||||
validate_enum(instance, schema, name);
|
// std::cerr << instance << " VS\n";
|
||||||
|
// std::cerr << schema_ << "\n";
|
||||||
|
// std::cerr << "\n";
|
||||||
|
|
||||||
|
const json *schema = &schema_;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const auto &ref = schema->find("$ref");
|
||||||
|
if (ref != schema->end()) {
|
||||||
|
std::string r = ref.value();
|
||||||
|
|
||||||
|
// do we have stored a schema which correspond to this reference
|
||||||
|
if (schema_references.find(r) == schema_references.end()) { // no
|
||||||
|
|
||||||
|
if (r[0] != '#')
|
||||||
|
throw std::logic_error("remote references are not yet implemented for ref " + r);
|
||||||
|
|
||||||
|
schema = schema_references["#"]; // root schema
|
||||||
|
|
||||||
|
// Aieee, need so much better parsing than this TODO
|
||||||
|
r = r.substr(1); // skip '#'
|
||||||
|
|
||||||
|
std::regex re("\\/([a-zA-Z0-9~%]+)");
|
||||||
|
for (auto match = std::sregex_iterator(r.begin(), r.end(), re), end = std::sregex_iterator();
|
||||||
|
match != end;
|
||||||
|
++match) {
|
||||||
|
|
||||||
|
std::string name = match->str().substr(1);
|
||||||
|
|
||||||
|
const auto &sub = schema->find(name);
|
||||||
|
if (sub == schema->end())
|
||||||
|
throw std::invalid_argument("reference schema " + r + " not found\n");
|
||||||
|
|
||||||
|
schema = &(*sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
schema_references[r] = schema;
|
||||||
|
} else
|
||||||
|
schema = schema_references[r];
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
} while (1); // loop in case of nested refs
|
||||||
|
|
||||||
|
validate_enum(instance, *schema, name);
|
||||||
|
|
||||||
switch (instance.type()) {
|
switch (instance.type()) {
|
||||||
case json::value_t::object:
|
case json::value_t::object:
|
||||||
validate_object(instance, schema, name);
|
validate_object(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::array:
|
case json::value_t::array:
|
||||||
validate_array(instance, schema, name);
|
validate_array(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::string:
|
case json::value_t::string:
|
||||||
validate_string(instance, schema, name);
|
validate_string(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::number_unsigned:
|
case json::value_t::number_unsigned:
|
||||||
validate_unsigned(instance, schema, name);
|
validate_unsigned(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::number_integer:
|
case json::value_t::number_integer:
|
||||||
validate_integer(instance, schema, name);
|
validate_integer(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::number_float:
|
case json::value_t::number_float:
|
||||||
validate_float(instance, schema, name);
|
validate_float(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::boolean:
|
case json::value_t::boolean:
|
||||||
validate_boolean(instance, schema, name);
|
validate_boolean(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case json::value_t::null:
|
case json::value_t::null:
|
||||||
validate_null(instance, schema, name);
|
validate_null(instance, *schema, name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::out_of_range("type '" + schema["type"].get<std::string>() +
|
assert(0 && "unexpected instance type for validation");
|
||||||
"' has no validator yet");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::map<std::string, const json *> schema_references;
|
||||||
|
|
||||||
|
void set_schema(const std::string &ref, const json &schema)
|
||||||
|
{
|
||||||
|
schema_references[ref] = &schema; /* replace or insert */
|
||||||
|
}
|
||||||
|
|
||||||
|
void validate(json &instance)
|
||||||
|
{
|
||||||
|
validate(instance, *schema_references["#"], "root");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user