diff --git a/.gitignore b/.gitignore index aceaf81..f20262d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,165 @@ build*/ *.sw? cmake-build-* -venv -env compile_commands.json + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +.idea/ + +### Project specific +CMakeUserPresets.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2eaa1a1..aab9b05 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,18 @@ repos: additional_dependencies: - mdformat-gfm - mdformat-tables + exclude: docs\/.* + - repo: https://github.com/executablebooks/mdformat + # TODO: Temporarily separate docs formatiing + # https://github.com/executablebooks/mdformat/issues/234 + # TODO: Disabled due to lack of colon-fence support + rev: 0.7.16 + hooks: + - id: mdformat + stages: [ manual ] + additional_dependencies: + - mdformat-myst + files: doc\/(?!README).*\.md$ - repo: https://github.com/python-jsonschema/check-jsonschema rev: 0.23.0 hooks: diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..3103d54 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,13 @@ +version: 2 + +python: + install: + - path: . + extra_requirements: + - docs +build: + os: ubuntu-22.04 + tools: + python: "3.11" +sphinx: + configuration: docs/conf.py diff --git a/README.md b/README.md index e9b80ed..5794d2a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ -[![Build Status](https://travis-ci.org/pboettch/json-schema-validator.svg?branch=master)](https://travis-ci.org/pboettch/json-schema-validator) - # JSON schema validator for JSON for Modern C++ -# What is it? + This is a C++ library for validating JSON documents based on a [JSON Schema](http://json-schema.org/) which itself should validate with @@ -15,146 +13,47 @@ Niels Lohmann et al develop a great JSON parser for C++ called [JSON for Modern C++](https://github.com/nlohmann/json). This validator is based on this library, hence the name. -External documentation is missing as well. However the API of the validator -is rather simple. - -# New in version 2 - -Although significant changes have been done for the 2nd version -(a complete rewrite) the API is compatible with the 1.0.0 release. Except for -the namespace which is now `nlohmann::json_schema`. - -Version **2** supports JSON schema draft 7, whereas 1 was supporting draft 4 -only. Please update your schemas. - -The primary change in 2 is the way a schema is used. While in version 1 the schema was -kept as a JSON-document and used again and again during validation, in version 2 the schema -is parsed into compiled C++ objects which are then used during validation. There are surely -still optimizations to be done, but validation speed has improved by factor 100 -or more. - -# Design goals - -The main goal of this validator is to produce *human-comprehensible* error -messages if a JSON-document/instance does not comply to its schema. - -By default this is done with exceptions thrown at the users with a helpful -message telling what's wrong with the document while validating. - -Starting with **2.0.0** the user can pass a `json_schema::basic_error_handler`-derived -object along with the instance to validate to receive a callback each time -a validation error occurs and decide what to do (throwing, counting, collecting). - -Another goal was to use Niels Lohmann's JSON-library. This is why the validator -lives in his namespace. - -# Thread-safety - -Instance validation is thread-safe and the same validator-object can be used by -different threads: - -The validate method is `const` which indicates the object is not modified when -being called: - -```C++ - json json_validator::validate(const json &) const; -``` - -Validator-object creation however is not thread-safe. A validator has to be -created in one (main?) thread once. - -# Weaknesses - -Numerical validation uses nlohmann-json's integer, unsigned and floating point -types, depending on if the schema type is "integer" or "number". Bignum -(i.e. arbitrary precision and range) is not supported at this time. - -# Building - -This library is based on Niels Lohmann's JSON-library and thus has -a build-dependency to it. +## Getting started -Currently at least version **3.6.0** of NLohmann's JSON library -is required. +Currently, this package only offers a C++ library interface, and is only +available via cmake's `FetchContent` and conan. It is highly recommended +to use cmake to link to this library -Various methods using CMake can be used to build this project. +Dependencies: -## Build out-of-source +- NLohmann's Json library: At least **3.6.0** + (See Github actions for officially tested versions) -Do not run cmake inside the source-dir. Rather create a dedicated build-dir: +### CMake configuration -```Bash -git clone https://github.com/pboettch/json-schema-validator.git -cd json-schema-validator -mkdir build -cd build -cmake [..] -make -make install # if needed -ctest # run unit, non-regression and test-suite tests -``` - -## Building as shared library - -By default a static library is built. Shared libraries can be generated by using -the `BUILD_SHARED_LIBS`-cmake variable: - -In your initial call to cmake simply add: - -```bash -cmake [..] -DBUILD_SHARED_LIBS=ON [..] -``` + -## nlohmann-json integration +Bellow is a minimum cmake configuration file using `FetchContent`: -As nlohmann-json is a dependency, this library tries find it. +```cmake +cmake_minimum_required(VERSION 3.11) -The cmake-configuration first checks if nlohmann-json is available as a cmake-target. This may be the case, because it is used as a submodule in a super-project which already provides and uses nlohmann-json. -Otherwise, it calls `find_package` for nlohmann-json and requires nlohmann-json to be installed on the system. +project(example) -### Building with Hunter package manager +include(FetchContent) -To enable access to nlohmann json library, Hunter can be used. Just run with `JSON_VALIDATOR_HUNTER=ON` option. No further dependencies needed +FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY pboettch/json-schema-validator + # Please use a specific version tag + GIT_TAG main + ) +FetchContent_MakeAvailable(nlohmann_json_schema_validator) -```bash -cmake [..] -DJSON_VALIDATOR_HUNTER=ON [..] +add_executable(example main.cpp) +target_link_libraries(example PRIVATE nlohmann_json_schema_validator::validator) ``` -### Building as a CMake-subdirectory from within another project - -Adding this library as a subdirectory to a parent project is one way of -building it. - -If the parent project already used `find_package()` to find the CMake-package of nlohmann_json or includes it as a submodule likewise. - -### Building directly, finding a CMake-package. (short) - -When nlohmann-json has been installed, it provides files which allows -CMake's `find_package()` to be used. - -This library is using this mechanism if `nlohmann_json::nlohmann_json`-target -does not exist. + -### Install +For more details about the available cmake options and recommended configurations +see [docs/cmake](docs/cmake/index.md) -Since version 2.1.0 this library can be installed and CMake-package-files will be -created accordingly. If the installation of nlohmann-json and this library -is done into default unix-system-paths CMake will be able to find this -library by simply doing: - -```CMake -find_package(nlohmann_json_schema_validator REQUIRED) -``` - -and - -```CMake -target_link_libraries( [..] nlohmann_json_schema_validator) -``` - -to build and link. - -## Code +### Api example See also `app/json-schema-validate.cpp`. @@ -252,7 +151,7 @@ int main() } ``` -# Compliance +## Compliance 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). @@ -263,7 +162,7 @@ cmake-variable `JSON_SCHEMA_TEST_SUITE_PATH` will enable the test-target(s). All required tests are **OK**. -# Format +## Format Optionally JSON-schema-validator can validate predefined or user-defined formats. Therefore a format-checker-function can be provided by the user which is called by @@ -287,7 +186,7 @@ json_validator validator(nullptr, // or loader-callback my_format_checker); // create validator ``` -## Default Checker +### Default Checker The library contains a default-checker, which does some checks. It needs to be provided manually to the constructor of the validator: @@ -301,7 +200,7 @@ Supported formats: `date-time, date, time, email, hostname, ipv4, ipv6, uuid, re More formats can be added in `src/string-format-check.cpp`. Please contribute implementions for missing json schema draft formats. -## Default value processing +### Default value processing As a result of the validation, the library returns a json patch including the default values of the specified schema. @@ -355,12 +254,4 @@ The example above will output the specified default values `{"height":10,"width" > Note that the default value specified in a `$ref` may be overridden by the current instance location. Also note that this behavior will break draft-7, but it is compliant to newer drafts (e.g. `2019-09` or `2020-12`). -# Contributing - -This project uses [`pre-commit`](https://pre-commit.com/) to enforce style-checks. Please install and run it before -creating commits and making pull requests. - -```console -$ pip install pre-commit -$ pre-commit install -``` + diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..e14b622 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing Guidelines + +Pull request are more than welcome on the +[GitHub page](https://github.com/pboettch/json-schema-validator). + +## Development environment + +This project uses [`pre-commit`](https://pre-commit.com/) to enforce style-checks. +These checks are enforced in the GitHub Actions, but it is encouraged to install +a development environment locally as well. + +```console +$ pip install -e .[dev] +$ pre-commit install +``` diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..b0c7ba8 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,16 @@ +# Changelog + +## New in version 2 + +Although significant changes have been done for the 2nd version +(a complete rewrite) the API is compatible with the 1.0.0 release. Except for +the namespace which is now `nlohmann::json_schema`. + +Version **2** supports JSON schema draft 7, whereas 1 was supporting draft 4 +only. Please update your schemas. + +The primary change in 2 is the way a schema is used. While in version 1 the schema was +kept as a JSON-document and used again and again during validation, in version 2 the schema +is parsed into compiled C++ objects which are then used during validation. There are surely +still optimizations to be done, but validation speed has improved by factor 100 +or more. diff --git a/docs/cmake/advanced.md b/docs/cmake/advanced.md new file mode 100644 index 0000000..a380e32 --- /dev/null +++ b/docs/cmake/advanced.md @@ -0,0 +1,3 @@ +# Advanced usage + +## Working with `FetchCotent` diff --git a/docs/cmake/index.md b/docs/cmake/index.md new file mode 100644 index 0000000..99113ad --- /dev/null +++ b/docs/cmake/index.md @@ -0,0 +1,16 @@ +# CMake configuration guide + +:::{toctree} +--- +maxdepth: 2 +glob: true +hidden: true +--- +::: + +:::{include} ../../README.md +--- +start-after: +end-before: +--- +::: diff --git a/docs/cmake/options.md b/docs/cmake/options.md new file mode 100644 index 0000000..1c6c9ac --- /dev/null +++ b/docs/cmake/options.md @@ -0,0 +1,5 @@ +# Configuration options + +## Available options + +## Working with CMake options diff --git a/docs/cmake/presets.md b/docs/cmake/presets.md new file mode 100644 index 0000000..ec06b7c --- /dev/null +++ b/docs/cmake/presets.md @@ -0,0 +1,5 @@ +# CMake Presets + +## Available presets + +## Working with presets diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2d8add9 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,26 @@ +project = 'Json Schema Validator' +copyright = '2023, Patrick Boettcher' +author = 'Patrick Boettcher' + +extensions = [ + "myst_parser", +] + +templates_path = [] +exclude_patterns = [ + 'build', + '_build', + 'Thumbs.db', + '.DS_Store', + "README.md", +] +source_suffix = [".md"] + + +html_theme = 'sphinx_rtd_theme' +html_static_path = ['_static'] + +myst_enable_extensions = [ + "tasklist", + "colon_fence", +] diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..8ae5565 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,20 @@ +# Json-Schema-Validator + +:::{toctree} +--- +maxdepth: 2 +glob: true +hidden: true +--- +CONTRIBUTING +changelog +roadmap +cmake/index.md +::: + +:::{include} ../README.md +--- +start-after: +end-before: +--- +::: diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..5af0441 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,37 @@ +# Roadmap + +## Design goals + +The main goal of this validator is to produce *human-comprehensible* error +messages if a JSON-document/instance does not comply to its schema. + +By default this is done with exceptions thrown at the users with a helpful +message telling what's wrong with the document while validating. + +Starting with **2.0.0** the user can pass a `json_schema::basic_error_handler`-derived +object along with the instance to validate to receive a callback each time +a validation error occurs and decide what to do (throwing, counting, collecting). + +Another goal was to use Niels Lohmann's JSON-library. This is why the validator +lives in his namespace. + +## Thread-safety + +Instance validation is thread-safe and the same validator-object can be used by +different threads: + +The validate method is `const` which indicates the object is not modified when +being called: + +```C++ + json json_validator::validate(const json &) const; +``` + +Validator-object creation however is not thread-safe. A validator has to be +created in one (main?) thread once. + +## Weaknesses + +Numerical validation uses nlohmann-json's integer, unsigned and floating point +types, depending on if the schema type is "integer" or "number". Bignum +(i.e. arbitrary precision and range) is not supported at this time. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f9b1eab --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,24 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "json-schema-validator-dev" +version = "0.0.0" +description = "Development environment json-schenma-validator" +readme = "README.md" +license = { file = "LICENSE" } + + +[project.optional-dependencies] +docs = [ + "sphinx >= 6.0", + "sphinx-rtd-theme", + "myst-parser", +] +dev = [ + "pre-commit", +] + +[tool.setuptools] +packages = []