├── .coveragerc ├── .github └── workflows │ ├── black.yml │ ├── build.yml │ ├── codeql-analysis.yml │ ├── mypy.yml │ └── ossar-analysis.yml ├── .gitignore ├── CHANGES ├── CONTRIBUTING.md ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── example ├── example.py └── requirements.txt ├── marshmallow_jsonschema ├── __init__.py ├── base.py ├── exceptions.py ├── extensions │ ├── __init__.py │ └── react_jsonschema_form.py └── validation.py ├── pyproject.toml ├── requirements-test.txt ├── requirements-tox.txt ├── requirements.txt ├── setup.py ├── tests ├── __init__.py ├── test_additional_properties.py ├── test_dump.py ├── test_imports.py ├── test_react_extension.py └── test_validation.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | omit = 4 | tests/* 5 | */tests/* 6 | 7 | [report] 8 | skip_covered = True 9 | fail_under=90 10 | exclude_lines = 11 | pragma: no cover 12 | def __repr__ 13 | raise NotImplementedError 14 | 15 | [html] 16 | directory = .reports/coverage 17 | -------------------------------------------------------------------------------- /.github/workflows/black.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: psf/black@stable 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Test Coverage 2 | 3 | on: ["push", "pull_request"] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | # supported python versions can be found here 11 | # https://github.com/actions/python-versions/releases 12 | # 13 | # Please bump to the latest unreleased candidate 14 | # when you come across this and have a moment to spare! 15 | python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] 16 | steps: 17 | - uses: actions/checkout@master 18 | - name: set up Python ${{ matrix.python-version }} 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install -U tox tox-gh-actions 26 | pip install -r requirements-tox.txt -r requirements-test.txt 27 | - name: Run tox 28 | run: | 29 | tox -e py 30 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '40 17 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.github/workflows/mypy.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | paths: 6 | - '*.py' 7 | 8 | jobs: 9 | mypy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Setup Python 13 | uses: actions/setup-python@v1 14 | with: 15 | python-version: 3.11.2 16 | architecture: x64 17 | - name: Checkout 18 | uses: actions/checkout@v1 19 | - name: Install mypy 20 | run: pip install mypy 21 | - name: Run mypy 22 | uses: sasanquaneuf/mypy-github-action@releases/v1 23 | with: 24 | checkName: 'mypy' # NOTE: this needs to be the same as the job name 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/workflows/ossar-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow integrates a collection of open source static analysis tools 2 | # with GitHub code scanning. For documentation, or to provide feedback, visit 3 | # https://github.com/github/ossar-action 4 | name: OSSAR 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | # The branches below must be a subset of the branches above 11 | branches: [ master ] 12 | schedule: 13 | - cron: '29 11 * * 2' 14 | 15 | jobs: 16 | OSSAR-Scan: 17 | # OSSAR runs on windows-latest. 18 | # ubuntu-latest and macos-latest support coming soon 19 | runs-on: windows-latest 20 | 21 | steps: 22 | - name: Checkout repository 23 | uses: actions/checkout@v2 24 | 25 | # Ensure a compatible version of dotnet is installed. 26 | # The [Microsoft Security Code Analysis CLI](https://aka.ms/mscadocs) is built with dotnet v3.1.201. 27 | # A version greater than or equal to v3.1.201 of dotnet must be installed on the agent in order to run this action. 28 | # GitHub hosted runners already have a compatible version of dotnet installed and this step may be skipped. 29 | # For self-hosted runners, ensure dotnet version 3.1.201 or later is installed by including this action: 30 | # - name: Install .NET 31 | # uses: actions/setup-dotnet@v1 32 | # with: 33 | # dotnet-version: '3.1.x' 34 | 35 | # Run open source static analysis tools 36 | - name: Run OSSAR 37 | uses: github/ossar-action@v1 38 | id: ossar 39 | 40 | # Upload results to the Security tab 41 | - name: Upload OSSAR results 42 | uses: github/codeql-action/upload-sarif@v1 43 | with: 44 | sarif_file: ${{ steps.ossar.outputs.sarifFile }} 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # pytype static type analyzer 135 | .pytype/ 136 | 137 | # Cython debug symbols 138 | cython_debug/ 139 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 0.13.0 (2021-10-21) 2 | - Fixes to field default #151 3 | - The default value for nested fields wasn't serialized. 4 | - The default value for other fields may be a callable and in that case it shouldn't be emitted into the schema. 5 | - set int to "integer" instead of "number" #152 6 | - Added fields.IPInterface marshmallow field type to python types mapping #155 7 | - 0.13.x is planned to be the last major release to officially support python 3.6 8 | which is EOL in December 2021 9 | - minimum supported version of marshmallow is currently 3.11.0 (technically this was 10 | true as of 0.12.0 because of the use of fields.IPInterface 11 | 0.12.0 (2021-05-22) 12 | - Add support for validate.Equal #135 13 | - Added fields.IP marshmallow field type to python types mapping #137 14 | - Use data_key when available for property names #139 15 | - UUID field inherits from the String field #144 16 | - fix: Change readonly to readOnly #147 17 | 0.11.1 (2021-01-28) 18 | - adding typing support and mypy to the build 19 | 0.11.0 (2021-01-26) 20 | - drop support for python 2 & 3.5, as well as marshmallow 2. 21 | Python >= 3.6 and marshmallow >= 3 are now required! 22 | Python 3.5 should still work - no breaking changes yet, 23 | it just isn't a part of the build anymore. #116 24 | - add optional support for marshmallow_enum and marshmallow_union. 25 | - Include type of Dict values #127 26 | Add support for specifying the type of Dict values. 27 | Prior to this change any information about the values in a 28 | dict - particularly nested schemas - was lost. 29 | - fix ReactJsonSchemaFormJSONSchema for marshmallow>=3.10.0 30 | - Change Makefile to build and upload wheel #131 31 | - move from travisci to github actions #132 32 | 0.10.0 (2020-03-03) 33 | - added ReactJsonSchemaFormJSONSchema extension 34 | - Add support for allow_none (#106 thanks @avilaton!) 35 | 0.9.0 (2020-01-18) 36 | 37 | 0.8.0 (2019-10-08) 38 | 39 | 0.7.0 (2019-08-11) 40 | 41 | 0.6.0 (2019-06-16) 42 | - lots of various fixes 43 | - fix compatibility with brutusin/json-form 44 | - drop support for python 3.3 45 | - fix BC breaks in marshmallow 3 (someday it will be released!!) 46 | - probably (hopefully?) the last major version to support py2! 47 | 48 | 0.5.0 (2018-07-17) 49 | - support for marshmallow 3 50 | 51 | 0.4.0 (2017-07-13) 52 | - add support for fields.List (thanks @Bartvds and @sdayu 53 | for tests & implementation) 54 | 55 | 0.3.0 (2016-06-12) 56 | - add support for marshmallow validators (see #14) 57 | 58 | 0.2.0 (2016-05-25) 59 | - add support for titles & descriptions in metadata 60 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Setting Up for Local Development 2 | ******************************** 3 | 4 | 1. Fork marshmallow_jsonschema on Github. 5 | 6 | :: 7 | 8 | $ git clone https://github.com/fuhrysteve/marshmallow-jsonschema.git 9 | $ cd marshmallow_jsonschema 10 | 11 | 2. Create a virtual environment and install all dependencies 12 | 13 | :: 14 | 15 | $ make venv 16 | 17 | 3. Install the pre-commit hooks, which will format and lint your git staged files. 18 | 19 | :: 20 | 21 | # The pre-commit CLI was installed above 22 | $ pre-commit install --allow-missing-config 23 | 24 | 25 | Running tests 26 | ************* 27 | 28 | To run all tests: :: 29 | 30 | $ pytest 31 | 32 | To run syntax checks: :: 33 | 34 | $ tox -e lint 35 | 36 | (Optional) To run tests in all supported Python versions in their own virtual environments (must have each interpreter installed): :: 37 | 38 | $ tox 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Stephen J. Fuhry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md requirements.txt requirements-test.txt requirements-tox.txt 2 | include LICENSE 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = marshmallow_jsonschema 2 | 3 | PYTHON_VERSION ?= 3.8 4 | VIRTUAL_ENV ?= .venv 5 | PYTHON ?= $(VIRTUAL_ENV)/bin/python 6 | 7 | 8 | REQUIREMENTS = requirements.txt 9 | REQUIREMENTS_TEST = requirements-test.txt 10 | REQUIREMENTS_TOX = requirements-tox.txt 11 | 12 | SHELL := /bin/bash -euo pipefail 13 | 14 | venv_init: 15 | pip install virtualenv 16 | if [ ! -d $(VIRTUAL_ENV) ]; then \ 17 | virtualenv -p python$(PYTHON_VERSION) --prompt="($(PROJECT))" $(VIRTUAL_ENV); \ 18 | fi 19 | 20 | venv: venv_init 21 | $(VIRTUAL_ENV)/bin/pip install -r $(REQUIREMENTS) 22 | $(VIRTUAL_ENV)/bin/pip install -r $(REQUIREMENTS_TEST) 23 | $(VIRTUAL_ENV)/bin/pip install -r $(REQUIREMENTS_TOX) 24 | 25 | tox: 26 | tox 27 | 28 | test: 29 | pytest 30 | 31 | test_coverage: 32 | pytest --cov-report html --cov-config .coveragerc --cov $(PROJECT) 33 | 34 | clean_build_and_dist: 35 | if [ -d build/ ]; then \ 36 | rm -rf build/ dist/ ; \ 37 | fi 38 | 39 | sdist: clean_build_and_dist 40 | python setup.py sdist 41 | 42 | bdist_wheel: 43 | pip install -U wheel 44 | python setup.py bdist_wheel 45 | 46 | twine: 47 | pip install -U twine 48 | 49 | pypitest: sdist bdist_wheel twine 50 | twine upload -r pypitest dist/* 51 | 52 | pypi: sdist bdist_wheel twine 53 | twine upload -r pypi dist/* 54 | 55 | 56 | clean_venv: 57 | rm -rf $(VIRTUAL_ENV) 58 | 59 | clean_pyc: 60 | find . -name \*.pyc -delete 61 | 62 | clean: clean_venv clean_pyc 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## marshmallow-jsonschema: JSON Schema formatting with marshmallow 2 | 3 |  4 | [](https://github.com/python/black) 5 | 6 | marshmallow-jsonschema translates marshmallow schemas into 7 | JSON Schema Draft v7 compliant jsonschema. See http://json-schema.org/ 8 | 9 | #### Why would I want my schema translated to JSON? 10 | 11 | What are the use cases for this? Let's say you have a 12 | marshmallow schema in python, but you want to render your 13 | schema as a form in another system (for example: a web browser 14 | or mobile device). 15 | 16 | #### Installation 17 | 18 | Requires python>=3.6 and marshmallow>=3.11. (For python 2 & marshmallow 2 support, please use marshmallow-jsonschema<0.11) 19 | 20 | ``` 21 | pip install marshmallow-jsonschema 22 | ``` 23 | 24 | #### Some Client tools can render forms using JSON Schema 25 | 26 | * [react-jsonschema-form](https://github.com/mozilla-services/react-jsonschema-form) (recommended) 27 | * See below extension for this excellent library! 28 | * https://github.com/brutusin/json-forms 29 | * https://github.com/jdorn/json-editor 30 | * https://github.com/ulion/jsonform 31 | 32 | ### Examples 33 | 34 | #### Simple Example 35 | 36 | ```python 37 | from marshmallow import Schema, fields 38 | from marshmallow_jsonschema import JSONSchema 39 | 40 | class UserSchema(Schema): 41 | username = fields.String() 42 | age = fields.Integer() 43 | birthday = fields.Date() 44 | 45 | user_schema = UserSchema() 46 | 47 | json_schema = JSONSchema() 48 | json_schema.dump(user_schema) 49 | ``` 50 | 51 | Yields: 52 | 53 | ```python 54 | {'properties': {'age': {'format': 'integer', 55 | 'title': 'age', 56 | 'type': 'number'}, 57 | 'birthday': {'format': 'date', 58 | 'title': 'birthday', 59 | 'type': 'string'}, 60 | 'username': {'title': 'username', 'type': 'string'}}, 61 | 'required': [], 62 | 'type': 'object'} 63 | ``` 64 | 65 | #### Nested Example 66 | 67 | ```python 68 | from marshmallow import Schema, fields 69 | from marshmallow_jsonschema import JSONSchema 70 | from tests import UserSchema 71 | 72 | 73 | class Athlete(object): 74 | user_schema = UserSchema() 75 | 76 | def __init__(self): 77 | self.name = 'sam' 78 | 79 | 80 | class AthleteSchema(Schema): 81 | user_schema = fields.Nested(JSONSchema) 82 | name = fields.String() 83 | 84 | 85 | athlete = Athlete() 86 | athlete_schema = AthleteSchema() 87 | 88 | athlete_schema.dump(athlete) 89 | ``` 90 | 91 | #### Complete example Flask application using brutisin/json-forms 92 | 93 |  94 | 95 | This example renders a form not dissimilar to how [wtforms](https://github.com/wtforms/wtforms) might render a form. 96 | 97 | However rather than rendering the form in python, the JSON Schema is rendered using the 98 | javascript library [brutusin/json-forms](https://github.com/brutusin/json-forms). 99 | 100 | 101 | ```python 102 | from flask import Flask, jsonify 103 | from marshmallow import Schema, fields 104 | from marshmallow_jsonschema import JSONSchema 105 | 106 | app = Flask(__name__) 107 | 108 | 109 | class UserSchema(Schema): 110 | name = fields.String() 111 | address = fields.String() 112 | 113 | 114 | @app.route('/schema') 115 | def schema(): 116 | schema = UserSchema() 117 | return jsonify(JSONSchema().dump(schema)) 118 | 119 | 120 | @app.route('/') 121 | def home(): 122 | return ''' 123 |
124 |