/* * Modern C++ JSON schema validator * * Licensed under the MIT License . * * Copyright (c) 2016 Patrick Boettcher . * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef NLOHMANN_JSON_SCHEMA_HPP__ #define NLOHMANN_JSON_SCHEMA_HPP__ #ifdef _WIN32 # ifdef JSON_SCHEMA_VALIDATOR_EXPORTS # define JSON_SCHEMA_VALIDATOR_API __declspec(dllexport) # else # define JSON_SCHEMA_VALIDATOR_API __declspec(dllimport) # endif #else # define JSON_SCHEMA_VALIDATOR_API #endif #include // make yourself a home - welcome to nlohmann's namespace namespace nlohmann { // a class representing a JSON-pointer RFC6901 // // examples of JSON pointers // // # - root of the current document // #item - refers to the object which is identified ("id") by `item` // in the current document // #/path/to/element // - refers to the element in /path/to from the root-document // // // The json_pointer-class stores everything in a string, which might seem bizarre // as parsing is done from a string to a string, but from_string() is also // doing some formatting. // // TODO // ~ and % - codec // needs testing and clarification regarding the '#' at the beginning class json_pointer { std::string str_; void from_string(const std::string &r); public: json_pointer(const std::string &s = "") { from_string(s); } void append(const std::string &elem) { str_.append(elem); } const std::string &to_string() const { return str_; } }; // 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_; json_pointer pointer_; protected: // decodes a JSON uri and replaces all or part of the currently stored values void from_string(const std::string &uri); std::tuple tie() const { return std::tie(urn_, proto_, hostname_, path_, pointer_.to_string()); } public: json_uri(const std::string &uri) { from_string(uri); } const std::string protocol() const { return proto_; } const std::string hostname() const { return hostname_; } const std::string path() const { return path_; } const json_pointer pointer() const { return pointer_; } const std::string url() const; // decode and encode strings for ~ and % escape sequences static std::string unescape(const std::string &); 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.from_string(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_.append("/" + 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_draft4 { extern json draft4_schema_builtin; class JSON_SCHEMA_VALIDATOR_API json_validator { std::vector> schema_store_; std::shared_ptr root_schema_; std::function schema_loader_ = nullptr; std::function format_check_ = nullptr; std::map schema_refs_; void validate(const json &instance, const json &schema_, const std::string &name); void validate_array(const json &instance, const json &schema_, const std::string &name); void validate_object(const json &instance, const json &schema_, const std::string &name); void validate_string(const json &instance, const json &schema, const std::string &name); void insert_schema(const json &input, const json_uri &id); public: json_validator(std::function loader = nullptr, std::function format = nullptr) : schema_loader_(loader), format_check_(format) { } // insert and set a root-schema void set_root_schema(const json &); // validate a json-document based on the root-schema void validate(const json &instance); }; } // json_schema_draft4 } // nlohmann #endif /* NLOHMANN_JSON_SCHEMA_HPP__ */