Pydantic: Generated JSON schema should contain $schema properties

Created on 5 May 2020  路  2Comments  路  Source: samuelcolvin/pydantic

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.5.1
            pydantic compiled: True
                 install path: /home/bernd/.local/share/virtualenvs/proj1/lib/python3.7/site-packages/pydantic
               python version: 3.7.6 (default, Apr 16 2020, 08:58:32)  [GCC 7.5.0]
                     platform: Linux-5.3.0-51-generic-x86_64-with-debian-buster-sid
     optional deps. installed: ['typing-extensions']
import pydantic

class MainModel(pydantic.BaseModel):
    """
    This is the description of the main model
    """
    snap: int = pydantic.Field(
        42,
        title='The Snap',
        description='this is the value of snap',
        gt=30,
        lt=50,
    )

    class Config:
        title = 'Main'


print(MainModel.schema_json(indent=2))

# output:
# {
#   "title": "Main",
#   "description": "This is the description of the main model",
#   "type": "object",
#   "properties": {
#     "snap": {
#       "title": "The Snap",
#       "description": "this is the value of snap",
#       "default": 42,
#       "exclusiveMinimum": 30,
#       "exclusiveMaximum": 50,
#       "type": "integer"
#     }
#   }
# }

But I miss the $schema property and therefore it's not clear which version of JSON schema pydantic is generating. The documentation refers to the latest version, but this version could change over time so it's not clear to me.

Also the specification says:

The "$schema" keyword SHOULD be used in a resource root schema. It MUST NOT appear in resource subschemas.

The documentation of the jsonschema libarary says

First, if the schema has a $schema property containing a known meta-schema 1 then the proper validator will be used. The specification recommends that all schemas contain $schema properties for this reason. If no $schema property is found, the default validator class is the latest released draft.

But this means that you have to specify the validator class (draft version) yourself or the jsonschema library uses their latest known draft version which is currently draft-07. But the latest version of the specification is draft2019-09.

So it would be great to add the used JSON schema draft/version ($schema property) when generating the JSON schema to help everyone in understand which version of the JSON schema specification the schema refers to.
As far as I know the currently available versions are

and I'm not sure which version pydantic is currently using

Schema feature request

Most helpful comment

Makes sense to me.

@tiangolo what do think?

All 2 comments

Makes sense to me.

@tiangolo what do think?

Yeah, I think it makes sense.


Some extra comments and info:

The current implementation is based on draft-07.

In OpenAPI, the $schema is not added/used. But that would probably not be a problem as the $schema would be added only to the JSON Schema generated for models and not fields. And for example, FastAPI uses the tools to generate the JSON Schema only for fields, not for models (I'm pretty sure :thinking: ). So the extra $schema would probably not affect those other use cases.

Some extra notes:

The currently generated schemas are also compatible with 2019-09. :nerd_face: :tada:

Here's the migration guide: https://json-schema.org/draft/2019-09/release-notes.html

The main changes, e.g. making format more permissive by default and optionally enforced by implementations, doesn't really affect here, as Pydantic is one of those implementations that adds extra validation for some fields adding format, in some cases with valid extensions.

Other things to note in version 2019-09: there's a new format keyword for UUID, and Pydantic already adds the format uuid for those fields, so, it implemented the new version before existing :sweat_smile: (that is also standard in previous versions of JSON Schema as the format can be extended).

There is now an official format duration with ISO 8601. That is already implemented with timedeltas, but the current format in Pydantic is time-delta. The format name could be updated to duration to support the new name in 2019-09.

The last change that affects here is that definitions was renamed to $defs, although the previous definitions is still supported for backwards compatibility. So, still valid, although could be updated.

Another note is that OpenAPI version 3.1.0 (still under development) is based on JSON Schema 2019-09. That means that once that is released, all the JSON Schemas that can be generated with Pydantic will also be valid with OpenAPI.

The main 2 specific points that currently differ are:

  • Tuples are supported by Pydantic and JSON Schema: Tuple[SubType1, SubType2, SubType3], but not yet by OpenAPI, they will be supported in OpenAPI 3.1.0.
  • exclusiveMaximum and exclusiveMinimum in all recent JSON Schemas are a number (as implemented in Pydantic) and in OpenAPI are a boolean (based on JSON Schema draft-00). That will be fully compatible with OpenAPI 3.1.0. Note that minimum and maximum don't have any conflict and work correctly in Pydantic, JSON Schema, and OpenAPI.
  • Other differences like OpenAPI currently has an example and JSON Schema has examples, and in OpenAPI 3.1.0 it will be all just examples, doesn't really affect Pydantic, as those are added by users in their code anyway (e.g. here in the FastAPI docs: https://fastapi.tiangolo.com/tutorial/schema-extra-example/ , that includes these technical details).
Was this page helpful?
0 / 5 - 0 ratings

Related issues

dmfigol picture dmfigol  路  38Comments

Gaunt picture Gaunt  路  19Comments

chopraaa picture chopraaa  路  18Comments

dand-oss picture dand-oss  路  19Comments

koxudaxi picture koxudaxi  路  25Comments