{"id":13399987,"url":"https://github.com/keleshev/schema","last_synced_at":"2025-05-13T22:00:20.924Z","repository":{"id":4337648,"uuid":"5473383","full_name":"keleshev/schema","owner":"keleshev","description":"Schema validation just got Pythonic","archived":false,"fork":false,"pushed_at":"2025-02-27T20:29:40.000Z","size":414,"stargazers_count":2914,"open_issues_count":101,"forks_count":213,"subscribers_count":52,"default_branch":"master","last_synced_at":"2025-05-06T21:09:33.513Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keleshev.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-08-19T18:56:20.000Z","updated_at":"2025-05-06T21:07:46.000Z","dependencies_parsed_at":"2024-01-13T06:58:40.428Z","dependency_job_id":"60bd5050-940c-4ea1-8999-a8da7ee83005","html_url":"https://github.com/keleshev/schema","commit_stats":{"total_commits":358,"total_committers":75,"mean_commits":4.773333333333333,"dds":0.7597765363128491,"last_synced_commit":"24a3045773eac497c659f24b32f24a281be9f286"},"previous_names":["halst/schema"],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keleshev%2Fschema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keleshev%2Fschema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keleshev%2Fschema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keleshev%2Fschema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keleshev","download_url":"https://codeload.github.com/keleshev/schema/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036806,"owners_count":22003651,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:46.115Z","updated_at":"2025-05-13T22:00:20.904Z","avatar_url":"https://github.com/keleshev.png","language":"Python","readme":"Schema validation just got Pythonic \n===============================================================================\n\n**schema** is a library for validating Python data structures, such as those\nobtained from config-files, forms, external services or command-line\nparsing, converted from JSON/YAML (or something else) to Python data-types.\n\n\n.. image:: https://secure.travis-ci.org/keleshev/schema.svg?branch=master\n    :target: https://travis-ci.org/keleshev/schema\n\n.. image:: https://img.shields.io/codecov/c/github/keleshev/schema.svg\n    :target: http://codecov.io/github/keleshev/schema\n\nExample\n----------------------------------------------------------------------------\n\nHere is a quick example to get a feeling of **schema**, validating a list of\nentries with personal information:\n\n.. code:: python\n    \n    from schema import Schema, And, Use, Optional, SchemaError\n    \n    schema = Schema(\n        [\n            {\n                \"name\": And(str, len),\n                \"age\": And(Use(int), lambda n: 18 \u003c= n \u003c= 99),\n                Optional(\"gender\"): And(\n                    str,\n                    Use(str.lower),\n                    lambda s: s in (\"squid\", \"kid\"),\n                ),\n            }\n        ]\n    )\n    \n    data = [\n        {\"name\": \"Sue\", \"age\": \"28\", \"gender\": \"Squid\"},\n        {\"name\": \"Sam\", \"age\": \"42\"},\n        {\"name\": \"Sacha\", \"age\": \"20\", \"gender\": \"KID\"},\n    ]\n    \n    validated = schema.validate(data)\n    \n    assert validated == [\n        {\"name\": \"Sue\", \"age\": 28, \"gender\": \"squid\"},\n        {\"name\": \"Sam\", \"age\": 42},\n        {\"name\": \"Sacha\", \"age\": 20, \"gender\": \"kid\"},\n    ]\n\n\n\nIf data is valid, ``Schema.validate`` will return the validated data\n(optionally converted with `Use` calls, see below).\n\nIf data is invalid, ``Schema`` will raise ``SchemaError`` exception.\nIf you just want to check that the data is valid, ``schema.is_valid(data)`` will\nreturn ``True`` or ``False``.\n\n\nInstallation\n-------------------------------------------------------------------------------\n\nUse `pip \u003chttp://pip-installer.org\u003e`_ or easy_install::\n\n    pip install schema\n\nAlternatively, you can just drop ``schema.py`` file into your project—it is\nself-contained.\n\n- **schema** is tested with Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9 and PyPy.\n- **schema** follows `semantic versioning \u003chttp://semver.org\u003e`_.\n\nHow ``Schema`` validates data\n-------------------------------------------------------------------------------\n\nTypes\n~~~~~\n\nIf ``Schema(...)`` encounters a type (such as ``int``, ``str``, ``object``,\netc.), it will check if the corresponding piece of data is an instance of that type,\notherwise it will raise ``SchemaError``.\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Schema\n\n    \u003e\u003e\u003e Schema(int).validate(123)\n    123\n\n    \u003e\u003e\u003e Schema(int).validate('123')\n    Traceback (most recent call last):\n    ...\n    schema.SchemaUnexpectedTypeError: '123' should be instance of 'int'\n\n    \u003e\u003e\u003e Schema(object).validate('hai')\n    'hai'\n\nCallables\n~~~~~~~~~\n\nIf ``Schema(...)`` encounters a callable (function, class, or object with\n``__call__`` method) it will call it, and if its return value evaluates to\n``True`` it will continue validating, else—it will raise ``SchemaError``.\n\n.. code:: python\n\n    \u003e\u003e\u003e import os\n\n    \u003e\u003e\u003e Schema(os.path.exists).validate('./')\n    './'\n\n    \u003e\u003e\u003e Schema(os.path.exists).validate('./non-existent/')\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: exists('./non-existent/') should evaluate to True\n\n    \u003e\u003e\u003e Schema(lambda n: n \u003e 0).validate(123)\n    123\n\n    \u003e\u003e\u003e Schema(lambda n: n \u003e 0).validate(-12)\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: \u003clambda\u003e(-12) should evaluate to True\n\n\"Validatables\"\n~~~~~~~~~~~~~~\n\nIf ``Schema(...)`` encounters an object with method ``validate`` it will run\nthis method on corresponding data as ``data = obj.validate(data)``. This method\nmay raise ``SchemaError`` exception, which will tell ``Schema`` that that piece\nof data is invalid, otherwise—it will continue validating.\n\nAn example of \"validatable\" is ``Regex``, that tries to match a string or a\nbuffer with the given regular expression (itself as a string, buffer or\ncompiled regex ``SRE_Pattern``):\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Regex\n    \u003e\u003e\u003e import re\n\n    \u003e\u003e\u003e Regex(r'^foo').validate('foobar')\n    'foobar'\n\n    \u003e\u003e\u003e Regex(r'^[A-Z]+$', flags=re.I).validate('those-dashes-dont-match')\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match'\n\nFor a more general case, you can use ``Use`` for creating such objects.\n``Use`` helps to use a function or type to convert a value while validating it:\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Use\n\n    \u003e\u003e\u003e Schema(Use(int)).validate('123')\n    123\n\n    \u003e\u003e\u003e Schema(Use(lambda f: open(f, 'a'))).validate('LICENSE-MIT')\n    \u003c_io.TextIOWrapper name='LICENSE-MIT' mode='a' encoding='UTF-8'\u003e\n\nDropping the details, ``Use`` is basically:\n\n.. code:: python\n\n    class Use(object):\n\n        def __init__(self, callable_):\n            self._callable = callable_\n\n        def validate(self, data):\n            try:\n                return self._callable(data)\n            except Exception as e:\n                raise SchemaError('%r raised %r' % (self._callable.__name__, e))\n\n\nSometimes you need to transform and validate part of data, but keep original data unchanged.\n``Const`` helps to keep your data safe:\n\n.. code:: python\n\n    \u003e\u003e from schema import Use, Const, And, Schema\n\n    \u003e\u003e from datetime import datetime\n\n    \u003e\u003e is_future = lambda date: datetime.now() \u003e date\n\n    \u003e\u003e to_json = lambda v: {\"timestamp\": v}\n\n    \u003e\u003e Schema(And(Const(And(Use(datetime.fromtimestamp), is_future)), Use(to_json))).validate(1234567890)\n    {\"timestamp\": 1234567890}\n\nNow you can write your own validation-aware classes and data types.\n\nLists, similar containers\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set``\nor ``frozenset``, it will validate contents of corresponding data container\nagainst all schemas listed inside that container and aggregate all errors:\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema([1, 0]).validate([1, 1, 0, 1])\n    [1, 1, 0, 1]\n\n    \u003e\u003e\u003e Schema((int, float)).validate((5, 7, 8, 'not int or float here'))\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: Or(\u003cclass 'int'\u003e, \u003cclass 'float'\u003e) did not validate 'not int or float here'\n    'not int or float here' should be instance of 'int'\n    'not int or float here' should be instance of 'float'\n\nDictionaries\n~~~~~~~~~~~~\n\nIf ``Schema(...)`` encounters an instance of ``dict``, it will validate data\nkey-value pairs:\n\n.. code:: python\n\n    \u003e\u003e\u003e d = Schema(\n    ...     {\"name\": str, \"age\": lambda n: 18 \u003c= n \u003c= 99}\n    ... ).validate(\n    ...     {\"name\": \"Sue\", \"age\": 28}\n    ... )\n\n    \u003e\u003e\u003e assert d == {'name': 'Sue', 'age': 28}\n\nYou can specify keys as schemas too:\n\n.. code:: python\n\n    \u003e\u003e\u003e schema = Schema({\n    ...     str: int,  # string keys should have integer values\n    ...     int: None,  # int keys should be always None\n    ... })\n\n    \u003e\u003e\u003e data = schema.validate({\n    ...     \"key1\": 1,\n    ...     \"key2\": 2,\n    ...     10: None,\n    ...     20: None,\n    ... })\n\n    \u003e\u003e\u003e schema.validate({\n    ...     \"key1\": 1,\n    ...     10: \"not None here\",\n    ... })\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: Key '10' error:\n    None does not match 'not None here'\n\nThis is useful if you want to check certain key-values, but don't care\nabout others:\n\n.. code:: python\n\n    \u003e\u003e\u003e schema = Schema({\n    ...     \"\u003cid\u003e\": int,\n    ...     \"\u003cfile\u003e\": Use(open),\n    ...     str: object,  # don't care about other str keys\n    ... })\n\n    \u003e\u003e\u003e data = schema.validate({\n    ...     \"\u003cid\u003e\": 10,\n    ...     \"\u003cfile\u003e\": \"README.rst\",\n    ...     \"--verbose\": True,\n    ... })\n\nYou can mark a key as optional as follows:\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema({\n    ...     \"name\": str,\n    ...     Optional(\"occupation\"): str,\n    ... }).validate({\"name\": \"Sam\"})\n    {'name': 'Sam'}\n\n``Optional`` keys can also carry a ``default``, to be used when no key in the\ndata matches:\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema({\n    ...     Optional(\"color\", default=\"blue\"): str,\n    ...     str: str,\n    ... }).validate({\"texture\": \"furry\"}) == {\n    ...     \"color\": \"blue\",\n    ...     \"texture\": \"furry\",\n    ... }\n    True\n\nDefaults are used verbatim, not passed through any validators specified in the\nvalue.\n\ndefault can also be a callable:\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Schema, Optional\n    \u003e\u003e\u003e Schema({Optional('data', default=dict): {}}).validate({}) == {'data': {}}\n    True\n\nAlso, a caveat: If you specify types, **schema** won't validate the empty dict:\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema({int:int}).is_valid({})\n    False\n\nTo do that, you need ``Schema(Or({int:int}, {}))``. This is unlike what happens with\nlists, where ``Schema([int]).is_valid([])`` will return True.\n\n\n**schema** has classes ``And`` and ``Or`` that help validating several schemas\nfor the same data:\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import And, Or\n\n    \u003e\u003e\u003e Schema({'age': And(int, lambda n: 0 \u003c n \u003c 99)}).validate({'age': 7})\n    {'age': 7}\n\n    \u003e\u003e\u003e Schema({'password': And(str, lambda s: len(s) \u003e 6)}).validate({'password': 'hai'})\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: Key 'password' error:\n    \u003clambda\u003e('hai') should evaluate to True\n\n    \u003e\u003e\u003e Schema(And(Or(int, float), lambda x: x \u003e 0)).validate(3.1415)\n    3.1415\n\nIn a dictionary, you can also combine two keys in a \"one or the other\" manner. To do\nso, use the `Or` class as a key:\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Or, Schema\n    \u003e\u003e\u003e schema = Schema({\n    ...    Or(\"key1\", \"key2\", only_one=True): str\n    ... })\n\n    \u003e\u003e\u003e schema.validate({\"key1\": \"test\"}) # Ok\n    {'key1': 'test'}\n\n    \u003e\u003e\u003e schema.validate({\"key1\": \"test\", \"key2\": \"test\"}) # SchemaError\n    Traceback (most recent call last):\n    ...\n    schema.SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition\n\nHooks\n~~~~~~~~~~\nYou can define hooks which are functions that are executed whenever a valid key:value is found.\nThe `Forbidden` class is an example of this.\n\nYou can mark a key as forbidden as follows:\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Forbidden\n    \u003e\u003e\u003e Schema({Forbidden('age'): object}).validate({'age': 50})\n    Traceback (most recent call last):\n    ...\n    schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50}\n\nA few things are worth noting. First, the value paired with the forbidden\nkey determines whether it will be rejected:\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema({Forbidden('age'): str, 'age': int}).validate({'age': 50})\n    {'age': 50}\n\nNote: if we hadn't supplied the 'age' key here, the call would have failed too, but with\nSchemaWrongKeyError, not SchemaForbiddenKeyError.\n\nSecond, Forbidden has a higher priority than standard keys, and consequently than Optional.\nThis means we can do that:\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema({Forbidden('age'): object, Optional(str): object}).validate({'age': 50})\n    Traceback (most recent call last):\n    ...\n    schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50}\n\nYou can also define your own hooks. The following hook will call `_my_function` if `key` is encountered.\n\n.. code:: python\n\n    from schema import Hook\n    def _my_function(key, scope, error):\n        print(key, scope, error)\n\n    Hook(\"key\", handler=_my_function)\n\nHere's an example where a `Deprecated` class is added to log warnings whenever a key is encountered:\n\n.. code:: python\n\n    from schema import Hook, Schema\n    class Deprecated(Hook):\n        def __init__(self, *args, **kwargs):\n            kwargs[\"handler\"] = lambda key, *args: logging.warn(f\"`{key}` is deprecated. \" + (self._error or \"\"))\n            super(Deprecated, self).__init__(*args, **kwargs)\n\n    Schema({Deprecated(\"test\", \"custom error message.\"): object}, ignore_extra_keys=True).validate({\"test\": \"value\"})\n    ...\n    WARNING: `test` is deprecated. custom error message.\n\nExtra Keys\n~~~~~~~~~~\n\nThe ``Schema(...)`` parameter ``ignore_extra_keys`` causes validation to ignore extra keys in a dictionary, and also to not return them after validating.\n\n.. code:: python\n\n    \u003e\u003e\u003e schema = Schema({'name': str}, ignore_extra_keys=True)\n    \u003e\u003e\u003e schema.validate({'name': 'Sam', 'age': '42'})\n    {'name': 'Sam'}\n\nIf you would like any extra keys returned, use ``object: object`` as one of the key/value pairs, which will match any key and any value.\nOtherwise, extra keys will raise a ``SchemaError``.\n\n\nCustomized Validation\n~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``Schema.validate`` method accepts additional keyword arguments. The\nkeyword arguments will be propagated to the ``validate`` method of any\nchild validatables (including any ad-hoc ``Schema`` objects), or the default\nvalue callable (if a callable is specified) for ``Optional`` keys.\n\nThis feature can be used together with inheritance of the ``Schema`` class\nfor customized validation.\n\nHere is an example where a \"post-validation\" hook that runs after validation\nagainst a sub-schema in a larger schema:\n\n.. code:: python\n\n    class EventSchema(schema.Schema):\n\n        def validate(self, data, _is_event_schema=True):\n            data = super(EventSchema, self).validate(data, _is_event_schema=False)\n            if _is_event_schema and data.get(\"minimum\", None) is None:\n                data[\"minimum\"] = data[\"capacity\"]\n            return data\n\n\n    events_schema = schema.Schema(\n        {\n            str: EventSchema({\n                \"capacity\": int,\n                schema.Optional(\"minimum\"): int,  # default to capacity\n            })\n        }\n    )\n\n\n    data = {'event1': {'capacity': 1}, 'event2': {'capacity': 2, 'minimum': 3}}\n    events = events_schema.validate(data)\n\n    assert events['event1']['minimum'] == 1  # == capacity\n    assert events['event2']['minimum'] == 3\n\n\nNote that the additional keyword argument ``_is_event_schema`` is necessary to\nlimit the customized behavior to the ``EventSchema`` object itself so that it\nwon't affect any recursive invoke of the ``self.__class__.validate`` for the\nchild schemas (e.g., the call to ``Schema(\"capacity\").validate(\"capacity\")``).\n\n\nUser-friendly error reporting\n-------------------------------------------------------------------------------\n\nYou can pass a keyword argument ``error`` to any of validatable classes\n(such as ``Schema``, ``And``, ``Or``, ``Regex``, ``Use``) to report this error\ninstead of a built-in one.\n\n.. code:: python\n\n    \u003e\u003e\u003e Schema(Use(int, error='Invalid year')).validate('XVII')\n    Traceback (most recent call last):\n    ...\n    schema.SchemaError: Invalid year\n\nYou can see all errors that occurred by accessing exception's ``exc.autos``\nfor auto-generated error messages, and ``exc.errors`` for errors\nwhich had ``error`` text passed to them.\n\nYou can exit with ``sys.exit(exc.code)`` if you want to show the messages\nto the user without traceback. ``error`` messages are given precedence in that\ncase.\n\nA JSON API example\n-------------------------------------------------------------------------------\n\nHere is a quick example: validation of\n`create a gist \u003chttp://developer.github.com/v3/gists/\u003e`_\nrequest from github API.\n\n.. code:: python\n\n    \u003e\u003e\u003e gist = '''{\"description\": \"the description for this gist\",\n    ...            \"public\": true,\n    ...            \"files\": {\n    ...                \"file1.txt\": {\"content\": \"String file contents\"},\n    ...                \"other.txt\": {\"content\": \"Another file contents\"}}}'''\n\n    \u003e\u003e\u003e from schema import Schema, And, Use, Optional\n\n    \u003e\u003e\u003e import json\n\n    \u003e\u003e\u003e gist_schema = Schema(\n    ...     And(\n    ...         Use(json.loads),  # first convert from JSON\n    ...         # use str since json returns unicode\n    ...         {\n    ...             Optional(\"description\"): str,\n    ...             \"public\": bool,\n    ...             \"files\": {str: {\"content\": str}},\n    ...         },\n    ...     )\n    ... )\n\n    \u003e\u003e\u003e gist = gist_schema.validate(gist)\n\n    # gist:\n    {u'description': u'the description for this gist',\n     u'files': {u'file1.txt': {u'content': u'String file contents'},\n                u'other.txt': {u'content': u'Another file contents'}},\n     u'public': True}\n\nUsing **schema** with `docopt \u003chttp://github.com/docopt/docopt\u003e`_\n-------------------------------------------------------------------------------\n\nAssume you are using **docopt** with the following usage-pattern:\n\n    Usage: my_program.py [--count=N] \u003cpath\u003e \u003cfiles\u003e...\n\nand you would like to validate that ``\u003cfiles\u003e`` are readable, and that\n``\u003cpath\u003e`` exists, and that ``--count`` is either integer from 0 to 5, or\n``None``.\n\nAssuming **docopt** returns the following dict:\n\n.. code:: python\n\n    \u003e\u003e\u003e args = {\n    ...     \"\u003cfiles\u003e\": [\"LICENSE-MIT\", \"setup.py\"],\n    ...     \"\u003cpath\u003e\": \"../\",\n    ...     \"--count\": \"3\",\n    ... }\n\nthis is how you validate it using ``schema``:\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Schema, And, Or, Use\n    \u003e\u003e\u003e import os\n\n    \u003e\u003e\u003e s = Schema({\n    ...     \"\u003cfiles\u003e\": [Use(open)],\n    ...     \"\u003cpath\u003e\": os.path.exists,\n    ...     \"--count\": Or(None, And(Use(int), lambda n: 0 \u003c n \u003c 5)),\n    ... })\n\n\n    \u003e\u003e\u003e args = s.validate(args)\n\n    \u003e\u003e\u003e args['\u003cfiles\u003e']\n    [\u003c_io.TextIOWrapper name='LICENSE-MIT' ...\u003e, \u003c_io.TextIOWrapper name='setup.py' ...]\n\n    \u003e\u003e\u003e args['\u003cpath\u003e']\n    '../'\n\n    \u003e\u003e\u003e args['--count']\n    3\n\nAs you can see, **schema** validated data successfully, opened files and\nconverted ``'3'`` to ``int``.\n\nJSON schema\n-----------\n\nYou can also generate standard `draft-07 JSON schema \u003chttps://json-schema.org/\u003e`_ from a dict ``Schema``.\nThis can be used to add word completion, validation, and documentation directly in code editors.\nThe output schema can also be used with JSON schema compatible libraries.\n\nJSON: Generating\n~~~~~~~~~~~~~~~~\n\nJust define your schema normally and call ``.json_schema()`` on it. The output is a Python dict, you need to dump it to JSON.\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Optional, Schema\n    \u003e\u003e\u003e import json\n    \u003e\u003e\u003e s = Schema({\n    ...     \"test\": str,\n    ...     \"nested\": {Optional(\"other\"): str},\n    ... })\n    \u003e\u003e\u003e json_schema = json.dumps(s.json_schema(\"https://example.com/my-schema.json\"))\n\n    # json_schema\n    {\n        \"type\":\"object\",\n        \"properties\": {\n            \"test\": {\"type\": \"string\"},\n            \"nested\": {\n                \"type\":\"object\",\n                \"properties\": {\n                    \"other\": {\"type\": \"string\"}\n                },\n                \"required\": [],\n                \"additionalProperties\": false\n            }\n        },\n        \"required\":[\n            \"test\",\n            \"nested\"\n        ],\n        \"additionalProperties\":false,\n        \"$id\":\"https://example.com/my-schema.json\",\n        \"$schema\":\"http://json-schema.org/draft-07/schema#\"\n    }\n\nYou can add descriptions for the schema elements using the ``Literal`` object instead of a string. The main schema can also have a description.\n\nThese will appear in IDEs to help your users write a configuration.\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Literal, Schema\n    \u003e\u003e\u003e import json\n    \u003e\u003e\u003e s = Schema(\n    ...     {Literal(\"project_name\", description=\"Names must be unique\"): str},\n    ...     description=\"Project schema\",\n    ... )\n    \u003e\u003e\u003e json_schema = json.dumps(s.json_schema(\"https://example.com/my-schema.json\"), indent=4)\n\n    # json_schema\n    {\n        \"type\": \"object\",\n        \"properties\": {\n            \"project_name\": {\n                \"description\": \"Names must be unique\",\n                \"type\": \"string\"\n            }\n        },\n        \"required\": [\n            \"project_name\"\n        ],\n        \"additionalProperties\": false,\n        \"$id\": \"https://example.com/my-schema.json\",\n        \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n        \"description\": \"Project schema\"\n    }\n\n\nJSON: Supported validations\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe resulting JSON schema is not guaranteed to accept the same objects as the library would accept, since some validations are not implemented or\nhave no JSON schema equivalent. This is the case of the ``Use`` and ``Hook`` objects for example.\n\nImplemented\n'''''''''''\n\n`Object properties \u003chttps://json-schema.org/understanding-json-schema/reference/object.html#properties\u003e`_\n    Use a dict literal. The dict keys are the JSON schema properties.\n\n    Example:\n\n    ``Schema({\"test\": str})``\n\n    becomes\n\n    ``{'type': 'object', 'properties': {'test': {'type': 'string'}}, 'required': ['test'], 'additionalProperties': False}``.\n\n    Please note that attributes are required by default. To create optional attributes use ``Optional``, like so:\n\n    ``Schema({Optional(\"test\"): str})``\n\n    becomes\n\n    ``{'type': 'object', 'properties': {'test': {'type': 'string'}}, 'required': [], 'additionalProperties': False}``\n\n    additionalProperties is set to true when at least one of the conditions is met:\n        - ignore_extra_keys is True\n        - at least one key is `str` or `object`\n\n    For example:\n\n    ``Schema({str: str})`` and ``Schema({}, ignore_extra_keys=True)``\n\n    both becomes\n\n    ``{'type': 'object', 'properties' : {}, 'required': [], 'additionalProperties': True}``\n\n    and\n\n    ``Schema({})``\n\n    becomes\n\n    ``{'type': 'object', 'properties' : {}, 'required': [], 'additionalProperties': False}``\n\nTypes\n    Use the Python type name directly. It will be converted to the JSON name:\n\n    - ``str`` -\u003e `string \u003chttps://json-schema.org/understanding-json-schema/reference/string.html\u003e`_\n    - ``int`` -\u003e `integer \u003chttps://json-schema.org/understanding-json-schema/reference/numeric.html#integer\u003e`_\n    - ``float`` -\u003e `number \u003chttps://json-schema.org/understanding-json-schema/reference/numeric.html#number\u003e`_\n    - ``bool`` -\u003e `boolean \u003chttps://json-schema.org/understanding-json-schema/reference/boolean.html\u003e`_\n    - ``list`` -\u003e `array \u003chttps://json-schema.org/understanding-json-schema/reference/array.html\u003e`_\n    - ``dict`` -\u003e `object \u003chttps://json-schema.org/understanding-json-schema/reference/object.html\u003e`_\n\n    Example:\n\n    ``Schema(float)``\n\n    becomes\n\n    ``{\"type\": \"number\"}``\n\n`Array items \u003chttps://json-schema.org/understanding-json-schema/reference/array.html#items\u003e`_\n    Surround a schema with ``[]``.\n\n    Example:\n\n    ``Schema([str])`` means an array of string and becomes:\n\n    ``{'type': 'array', 'items': {'type': 'string'}}``\n\n`Enumerated values \u003chttps://json-schema.org/understanding-json-schema/reference/generic.html#enumerated-values\u003e`_\n    Use `Or`.\n\n    Example:\n\n    ``Schema(Or(1, 2, 3))`` becomes\n\n    ``{\"enum\": [1, 2, 3]}``\n\n`Constant values \u003chttps://json-schema.org/understanding-json-schema/reference/generic.html#constant-values\u003e`_\n    Use the value itself.\n\n    Example:\n\n    ``Schema(\"name\")`` becomes\n\n    ``{\"const\": \"name\"}``\n\n`Regular expressions \u003chttps://json-schema.org/understanding-json-schema/reference/regular_expressions.html\u003e`_\n    Use ``Regex``.\n\n    Example:\n\n    ``Schema(Regex(\"^v\\d+\"))`` becomes\n\n    ``{'type': 'string', 'pattern': '^v\\\\d+'}``\n\n`Annotations (title and description) \u003chttps://json-schema.org/understanding-json-schema/reference/generic.html#annotations\u003e`_\n    You can use the ``name`` and ``description`` parameters of the ``Schema`` object init method.\n\n    To add description to keys, replace a str with a ``Literal`` object.\n\n    Example:\n\n    ``Schema({Literal(\"test\", description=\"A description\"): str})``\n\n    is equivalent to\n\n    ``Schema({\"test\": str})``\n\n    with the description added to the resulting JSON schema.\n\n`Combining schemas with allOf \u003chttps://json-schema.org/understanding-json-schema/reference/combining.html#allof\u003e`_\n    Use ``And``\n\n    Example:\n\n    ``Schema(And(str, \"value\"))``\n\n    becomes\n\n    ``{\"allOf\": [{\"type\": \"string\"}, {\"const\": \"value\"}]}``\n\n    Note that this example is not really useful in the real world, since ``const`` already implies the type.\n\n`Combining schemas with anyOf \u003chttps://json-schema.org/understanding-json-schema/reference/combining.html#anyof\u003e`_\n    Use ``Or``\n\n    Example:\n\n    ``Schema(Or(str, int))``\n\n    becomes\n\n    ``{\"anyOf\": [{\"type\": \"string\"}, {\"type\": \"integer\"}]}``\n\n\nNot implemented\n'''''''''''''''\n\nThe following JSON schema validations cannot be generated from this library.\n\n- `String length \u003chttps://json-schema.org/understanding-json-schema/reference/string.html#length\u003e`_\n    However, those can be implemented using ``Regex``\n- `String format \u003chttps://json-schema.org/understanding-json-schema/reference/string.html#format\u003e`_\n    However, those can be implemented using ``Regex``\n- `Object dependencies \u003chttps://json-schema.org/understanding-json-schema/reference/object.html#dependencies\u003e`_\n- `Array length \u003chttps://json-schema.org/understanding-json-schema/reference/array.html#length\u003e`_\n- `Array uniqueness \u003chttps://json-schema.org/understanding-json-schema/reference/array.html#uniqueness\u003e`_\n- `Numeric multiples \u003chttps://json-schema.org/understanding-json-schema/reference/numeric.html#multiples\u003e`_\n- `Numeric ranges \u003chttps://json-schema.org/understanding-json-schema/reference/numeric.html#range\u003e`_\n- `Property Names \u003chttps://json-schema.org/understanding-json-schema/reference/object.html#property-names\u003e`_\n    Not implemented. We suggest listing the possible keys instead. As a tip, you can use ``Or`` as a dict key.\n\n    Example:\n\n    ``Schema({Or(\"name1\", \"name2\"): str})``\n- `Annotations (default and examples) \u003chttps://json-schema.org/understanding-json-schema/reference/generic.html#annotations\u003e`_\n- `Combining schemas with oneOf \u003chttps://json-schema.org/understanding-json-schema/reference/combining.html#oneof\u003e`_\n- `Not \u003chttps://json-schema.org/understanding-json-schema/reference/combining.html#not\u003e`_\n- `Object size \u003chttps://json-schema.org/understanding-json-schema/reference/object.html#size\u003e`_\n- `additionalProperties having a different schema (true and false is supported)`\n\n\nJSON: Minimizing output size\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nExplicit Reuse\n''''''''''''''\n\nIf your JSON schema is big and has a lot of repetition, it can be made simpler and smaller by defining Schema objects as reference.\nThese references will be placed in a \"definitions\" section in the main schema.\n\n`You can look at the JSON schema documentation for more information \u003chttps://json-schema.org/understanding-json-schema/structuring.html#reuse\u003e`_\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Optional, Schema\n    \u003e\u003e\u003e import json\n    \u003e\u003e\u003e s = Schema({\n    ...     \"test\": str,\n    ...     \"nested\": Schema({Optional(\"other\"): str}, name=\"nested\", as_reference=True)\n    ... })\n    \u003e\u003e\u003e json_schema = json.dumps(s.json_schema(\"https://example.com/my-schema.json\"), indent=4)\n\n    # json_schema\n    {\n        \"type\": \"object\",\n        \"properties\": {\n            \"test\": {\n                \"type\": \"string\"\n            },\n            \"nested\": {\n                \"$ref\": \"#/definitions/nested\"\n            }\n        },\n        \"required\": [\n            \"test\",\n            \"nested\"\n        ],\n        \"additionalProperties\": false,\n        \"$id\": \"https://example.com/my-schema.json\",\n        \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n        \"definitions\": {\n            \"nested\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"other\": {\n                        \"type\": \"string\"\n                    }\n                },\n                \"required\": [],\n                \"additionalProperties\": false\n            }\n        }\n    }\n\nThis becomes really useful when using the same object several times\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Optional, Or, Schema\n    \u003e\u003e\u003e import json\n    \u003e\u003e\u003e language_configuration = Schema(\n    ...     {\"autocomplete\": bool, \"stop_words\": [str]},\n    ...     name=\"language\",\n    ...     as_reference=True,\n    ... )\n    \u003e\u003e\u003e s = Schema({Or(\"ar\", \"cs\", \"de\", \"el\", \"eu\", \"en\", \"es\", \"fr\"): language_configuration})\n    \u003e\u003e\u003e json_schema = json.dumps(s.json_schema(\"https://example.com/my-schema.json\"), indent=4)\n\n    # json_schema\n    {\n        \"type\": \"object\",\n        \"properties\": {\n            \"ar\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"cs\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"de\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"el\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"eu\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"en\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"es\": {\n                \"$ref\": \"#/definitions/language\"\n            },\n            \"fr\": {\n                \"$ref\": \"#/definitions/language\"\n            }\n        },\n        \"required\": [],\n        \"additionalProperties\": false,\n        \"$id\": \"https://example.com/my-schema.json\",\n        \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n        \"definitions\": {\n            \"language\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"autocomplete\": {\n                        \"type\": \"boolean\"\n                    },\n                    \"stop_words\": {\n                        \"type\": \"array\",\n                        \"items\": {\n                            \"type\": \"string\"\n                        }\n                    }\n                },\n                \"required\": [\n                    \"autocomplete\",\n                    \"stop_words\"\n                ],\n                \"additionalProperties\": false\n            }\n        }\n    }\n\nAutomatic reuse\n'''''''''''''''\n\nIf you want to minimize the output size without using names explicitly, you can have the library generate hashes of parts of the output JSON\nschema and use them as references throughout.\n\nEnable this behaviour by providing the parameter ``use_refs`` to the json_schema method.\n\nBe aware that this method is less often compatible with IDEs and JSON schema libraries.\nIt produces a JSON schema that is more difficult to read by humans.\n\n.. code:: python\n\n    \u003e\u003e\u003e from schema import Optional, Or, Schema\n    \u003e\u003e\u003e import json\n    \u003e\u003e\u003e language_configuration = Schema({\"autocomplete\": bool, \"stop_words\": [str]})\n    \u003e\u003e\u003e s = Schema({Or(\"ar\", \"cs\", \"de\", \"el\", \"eu\", \"en\", \"es\", \"fr\"): language_configuration})\n    \u003e\u003e\u003e json_schema = json.dumps(s.json_schema(\"https://example.com/my-schema.json\", use_refs=True), indent=4)\n\n    # json_schema\n    {\n        \"type\": \"object\",\n        \"properties\": {\n            \"ar\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"autocomplete\": {\n                        \"type\": \"boolean\",\n                        \"$id\": \"#6456104181059880193\"\n                    },\n                    \"stop_words\": {\n                        \"type\": \"array\",\n                        \"items\": {\n                            \"type\": \"string\",\n                            \"$id\": \"#1856069563381977338\"\n                        }\n                    }\n                },\n                \"required\": [\n                    \"autocomplete\",\n                    \"stop_words\"\n                ],\n                \"additionalProperties\": false\n            },\n            \"cs\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"autocomplete\": {\n                        \"$ref\": \"#6456104181059880193\"\n                    },\n                    \"stop_words\": {\n                        \"type\": \"array\",\n                        \"items\": {\n                            \"$ref\": \"#1856069563381977338\"\n                        },\n                        \"$id\": \"#-5377945144312515805\"\n                    }\n                },\n                \"required\": [\n                    \"autocomplete\",\n                    \"stop_words\"\n                ],\n                \"additionalProperties\": false\n            },\n            \"de\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"autocomplete\": {\n                        \"$ref\": \"#6456104181059880193\"\n                    },\n                    \"stop_words\": {\n                        \"$ref\": \"#-5377945144312515805\"\n                    }\n                },\n                \"required\": [\n                    \"autocomplete\",\n                    \"stop_words\"\n                ],\n                \"additionalProperties\": false,\n                \"$id\": \"#-8142886105174600858\"\n            },\n            \"el\": {\n                \"$ref\": \"#-8142886105174600858\"\n            },\n            \"eu\": {\n                \"$ref\": \"#-8142886105174600858\"\n            },\n            \"en\": {\n                \"$ref\": \"#-8142886105174600858\"\n            },\n            \"es\": {\n                \"$ref\": \"#-8142886105174600858\"\n            },\n            \"fr\": {\n                \"$ref\": \"#-8142886105174600858\"\n            }\n        },\n        \"required\": [],\n        \"additionalProperties\": false,\n        \"$id\": \"https://example.com/my-schema.json\",\n        \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n    }\n","funding_links":[],"categories":["Python","Data Validation","资源列表","Libraries in Python","Data Format \u0026 I/O","数据验证","Data Validation [🔝](#readme)","Awesome Python","Data validation"],"sub_categories":["数据验证","For Python","Data Validation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeleshev%2Fschema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeleshev%2Fschema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeleshev%2Fschema/lists"}