How can I generate JSON schema for list of dataclass with pydantic?

Viewed 1610

I am trying to generate JSON Schema from python data classes that contain lists of other data classes as parameters. I don't really care about any functionality from pydantic other than generating json schema, since I am just using the output to auto-generate a web frontend. So solutions using other libraries are fine.

from typing import List
from dataclasses import dataclass
import pydantic

@dataclass()
class SomeParameters:
    a: int = 5

@dataclass()
class SomeMoreParameters:
    another: List[SomeParameters]

pydantic_cls = pydantic.dataclasses.dataclass(SomeMoreParameters)
schema = pydantic_cls.__pydantic_model__.schema()

This code errors with the following stacktrace (you can use SKIP_CYTHON=1 pip install --no-cache-dir --no-binary :all: pydantic to install pydantic so that you can debug into it):

Traceback (most recent call last):
  File "/home/veith/Projects/job-ui-parametrization/debug.py", line 17, in <module>
    schema = pydantic_cls.__pydantic_model__.schema()
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/main.py", line 647, in schema
    s = model_schema(cls, by_alias=by_alias, ref_template=ref_template)
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 185, in model_schema
    m_schema, m_definitions, nested_models = model_process_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 617, in model_process_schema
    m_schema, m_definitions, nested_models = model_type_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 658, in model_type_schema
    f_schema, f_definitions, f_nested_models = field_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 258, in field_schema
    f_schema, f_definitions, f_nested_models = field_type_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 498, in field_type_schema
    items_schema, f_definitions, f_nested_models = field_singleton_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 848, in field_singleton_schema
    return field_singleton_sub_fields_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 736, in field_singleton_sub_fields_schema
    return field_type_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 563, in field_type_schema
    f_schema, f_definitions, f_nested_models = field_singleton_schema(
  File "/home/veith/Projects/job-ui-parametrization/venv/lib/python3.9/site-packages/pydantic/schema.py", line 947, in field_singleton_schema
    raise ValueError(f'Value not declarable with JSON Schema, field: {field}')
ValueError: Value not declarable with JSON Schema, field: name='_another' type=SomeParameters required=True

Process finished with exit code 1

Now according to JSON Schema documentation an array of things is valid. The pydantic documentation uses list of integers, which also works for me. I would expect that I can also use custom types in a list. The documentation further states Nested dataclasses are supported both in dataclasses and normal models.

Am I doing something wrong/not doing something that I should be doing? Or am I misunderstanding something, and this is actually not allowed? What are some alternatives if this is the case?

2 Answers

Interesting, your code is working for me on Python 3.9.1 (Windows). Just curious, what version of pydantic are you using?

Here is code that is working for me. Note you can use pydantic drop-in dataclasses to simplify the JSON schema generation a bit.

from typing import List
# from dataclasses import dataclass
from pydantic.dataclasses import dataclass

@dataclass
class SomeParameters:
    a: int = 5

@dataclass
class SomeMoreParameters:
    another: List[SomeParameters]

# pydantic_cls = pydantic.dataclasses.dataclass(SomeMoreParameters)
schema = SomeMoreParameters.__pydantic_model__.schema()
print(schema)

Output:

{'title': 'SomeMoreParameters', 'type': 'object', 'properties': {'another': {'title': 'Another', 'type': 'array', 'items': {'$ref': '#/definitions/SomeParameters'}}}, 'required': ['another'], 'definitions': {'SomeParameters': {'title': 'SomeParameters', 'type': 'object', 'properties': {'a': {'title': 'A', 'default': 5, 'type': 'integer'}}}}}

Note: I am using pydantic==1.8.2.

Related