Schema a now "parsed" into C++-validator-objects in a first step and then validation takes place with these objects. Errors are now handled via a user-provided error-handler allowing the user to collect all errors at once or bail out when a certain threshold is reached. Fixes #36 and #8. One (sub-)schema can now be referenced with different URIs. Fixes #9 JSON schema draft 7 is now supported. Fixes #35
158 lines
4.0 KiB
C++
158 lines
4.0 KiB
C++
/*
|
|
* JSON schema validator for JSON for modern C++
|
|
*
|
|
* Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
#ifndef NLOHMANN_JSON_SCHEMA_HPP__
|
|
#define NLOHMANN_JSON_SCHEMA_HPP__
|
|
|
|
#ifdef _WIN32
|
|
# if defined(JSON_SCHEMA_VALIDATOR_EXPORTS)
|
|
# define JSON_SCHEMA_VALIDATOR_API __declspec(dllexport)
|
|
# elif defined(JSON_SCHEMA_VALIDATOR_IMPORTS)
|
|
# define JSON_SCHEMA_VALIDATOR_API __declspec(dllimport)
|
|
# else
|
|
# define JSON_SCHEMA_VALIDATOR_API
|
|
# endif
|
|
#else
|
|
# define JSON_SCHEMA_VALIDATOR_API
|
|
#endif
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#ifdef NLOHMANN_JSON_VERSION_MAJOR
|
|
# if NLOHMANN_JSON_VERSION_MAJOR < 3 || NLOHMANN_JSON_VERSION_MINOR < 5 || NLOHMANN_JSON_VERSION_PATCH < 0
|
|
# error "Please use this library with NLohmann's JSON version 3.5.0 or higher"
|
|
# endif
|
|
#else
|
|
# error "expected existing NLOHMANN_JSON_VERSION_MAJOR preproc variable, please update to NLohmann's JSON 3.5.0"
|
|
#endif
|
|
|
|
// make yourself a home - welcome to nlohmann's namespace
|
|
namespace nlohmann
|
|
{
|
|
|
|
// A class representing a JSON-URI for schemas derived from
|
|
// section 8 of JSON Schema: A Media Type for Describing JSON Documents
|
|
// draft-wright-json-schema-00
|
|
//
|
|
// New URIs can be derived from it using the derive()-method.
|
|
// This is useful for resolving refs or subschema-IDs in json-schemas.
|
|
//
|
|
// This is done implement the requirements described in section 8.2.
|
|
//
|
|
class JSON_SCHEMA_VALIDATOR_API json_uri
|
|
{
|
|
std::string urn_;
|
|
|
|
std::string proto_;
|
|
std::string hostname_;
|
|
std::string path_;
|
|
nlohmann::json::json_pointer pointer_;
|
|
|
|
protected:
|
|
// decodes a JSON uri and replaces all or part of the currently stored values
|
|
void update(const std::string &uri);
|
|
|
|
std::tuple<std::string, std::string, std::string, std::string, std::string> tie() const
|
|
{
|
|
return std::tie(urn_, proto_, hostname_, path_, pointer_);
|
|
}
|
|
|
|
public:
|
|
json_uri(const std::string &uri)
|
|
{
|
|
update(uri);
|
|
}
|
|
|
|
const std::string protocol() const { return proto_; }
|
|
const std::string hostname() const { return hostname_; }
|
|
const std::string path() const { return path_; }
|
|
|
|
const nlohmann::json::json_pointer pointer() const { return pointer_; }
|
|
|
|
const std::string url() const { return location(); }
|
|
const std::string location() const;
|
|
|
|
static std::string escape(const std::string &);
|
|
|
|
// create a new json_uri based in this one and the given uri
|
|
// resolves relative changes (pathes or pointers) and resets part if proto or hostname changes
|
|
json_uri derive(const std::string &uri) const
|
|
{
|
|
json_uri u = *this;
|
|
u.update(uri);
|
|
return u;
|
|
}
|
|
|
|
// append a pointer-field to the pointer-part of this uri
|
|
json_uri append(const std::string &field) const
|
|
{
|
|
json_uri u = *this;
|
|
u.pointer_ = nlohmann::json::json_pointer(u.pointer_.to_string() + '/' + escape(field));
|
|
return u;
|
|
}
|
|
|
|
std::string to_string() const;
|
|
|
|
friend bool operator<(const json_uri &l, const json_uri &r)
|
|
{
|
|
return l.tie() < r.tie();
|
|
}
|
|
|
|
friend bool operator==(const json_uri &l, const json_uri &r)
|
|
{
|
|
return l.tie() == r.tie();
|
|
}
|
|
|
|
friend std::ostream &operator<<(std::ostream &os, const json_uri &u);
|
|
};
|
|
|
|
namespace json_schema
|
|
{
|
|
|
|
extern json draft7_schema_builtin;
|
|
|
|
class basic_error_handler
|
|
{
|
|
bool error_{false};
|
|
|
|
public:
|
|
virtual void error(const std::string & /*path*/, const json & /* instance */, const std::string & /*message*/)
|
|
{
|
|
error_ = true;
|
|
}
|
|
|
|
void reset() { error_ = false; }
|
|
operator bool() const { return error_; }
|
|
};
|
|
|
|
class root_schema;
|
|
|
|
class JSON_SCHEMA_VALIDATOR_API json_validator
|
|
{
|
|
std::unique_ptr<root_schema> root_;
|
|
|
|
public:
|
|
json_validator(std::function<void(const json_uri &, json &)> loader = nullptr,
|
|
std::function<void(const std::string &, const std::string &)> format = nullptr);
|
|
~json_validator();
|
|
|
|
// insert and set thea root-schema
|
|
void set_root_schema(const json &);
|
|
|
|
// validate a json-document based on the root-schema
|
|
void validate(const json &);
|
|
|
|
// validate a json-document based on the root-schema with a custom error-handler
|
|
void validate(const json &, basic_error_handler &);
|
|
};
|
|
|
|
} // namespace json_schema
|
|
} // namespace nlohmann
|
|
|
|
#endif /* NLOHMANN_JSON_SCHEMA_HPP__ */
|