| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- #include <cstdio>
- #include <cstdlib>
- #include <filesystem>
- #include <iostream>
- #include <sstream>
- #include <stdexcept>
- #include <string_view>
- #include <curl/curl.h>
- #include <jvalidate/adapter.h>
- #include <jvalidate/adapters/jsoncpp.h>
- #include <jvalidate/compat/curl.h>
- #include <jvalidate/enum.h>
- #include <jvalidate/forward.h>
- #include <jvalidate/schema.h>
- #include <jvalidate/status.h>
- #include <jvalidate/uri.h>
- #include <jvalidate/validator.h>
- #include <json/value.h>
- #include <json/writer.h>
- using jvalidate::adapter::load_file;
- using jvalidate::adapter::load_stream;
- struct ProgramArgs {
- ProgramArgs(std::string_view program, std::vector<std::string_view> args) {
- size_t nargs = 0;
- for (size_t i = 0; i < args.size(); ++i) {
- if (args[i] == "--verbose" || args[i] == "-v") {
- verbose = true;
- } else if (args[i] == "--explain") {
- format_as_explaination = true;
- } else {
- switch (nargs++) {
- case 0:
- schema = args[i];
- break;
- case 1:
- object = args[i];
- break;
- }
- }
- }
- if (nargs != 2) {
- throw std::invalid_argument("usage: " + std::string(program) +
- " [--verbose|-v] [--explain] schema object");
- }
- }
- bool verbose = false;
- bool format_as_explaination = false;
- std::string_view schema;
- std::string_view object;
- };
- int main(int argc, char const * const * argv) {
- ProgramArgs const args{argv[0], {argv + 1, argv + argc}};
- Json::Value jschema;
- Json::Value jobject;
- if (std::string error; !load_file(args.schema, jschema, error)) {
- std::cerr << "Error loading schema: " << error << std::endl;
- return EXIT_FAILURE;
- }
- if (std::string error; !load_file(args.object, jobject, error)) {
- std::cerr << "Error loading schema: " << error << std::endl;
- return EXIT_FAILURE;
- }
- using enum jvalidate::schema::Version;
- jvalidate::Schema schema(jschema, Draft2020_12, &jvalidate::curl_get<Json::Value>);
- jvalidate::ValidationResult result;
- bool compact_error = !args.verbose && !args.format_as_explaination;
- if (jvalidate::Validator(schema, {.only_return_results_with_error = compact_error})
- .validate(jobject, &result)) {
- std::cout << result << "\n";
- return EXIT_SUCCESS;
- }
- if (!args.format_as_explaination) {
- std::cout << result << "\n";
- return EXIT_FAILURE;
- }
- Json::Value json;
- {
- std::stringstream ss;
- ss << result;
- std::string _;
- load_stream(ss, json, _);
- }
- std::map<std::string, Json::Value> because;
- for (Json::Value const & elem : json["details"]) {
- std::string const & path = elem["evaluationPath"].asString();
- if (size_t pos = path.find("/if"); pos != std::string::npos && elem.isMember("errors")) {
- because.emplace(path.substr(0, pos), elem);
- }
- }
- Json::Value out;
- for (Json::Value & elem : json["details"]) {
- if (!elem.isMember("errors")) {
- continue;
- }
- for (std::string const & path = elem["evaluationPath"].asString();
- auto const & [key, reason] : because) {
- if (path.starts_with(key) && path != reason["evaluationPath"].asString()) {
- elem["because"].append(reason);
- }
- }
- out.append(std::move(elem));
- }
- std::cout << out << std::endl;
- return EXIT_FAILURE;
- }
|