3

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?

3 Answers 3

3

This is a bug introduced with pydantic 1.9. I have contributed a pull request fixing this issue here: https://github.com/samuelcolvin/pydantic/pull/3819

Sign up to request clarification or add additional context in comments.

1 Comment

The bug is solved in 1.9.1.
3

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.

1 Comment

I've ran into the same issue with pydantic==1.9.0 and the drop-in replacement solves the problem. I hope someone can explain why... or maybe it's just a bug in pyndatic?
2

On pydantic>=2.5.0 this can be achieved through the mean of TypeAdapter (see doc)

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

@dataclass
class SomeParameters:
    a: int = 5

@dataclass
class SomeMoreParameters:
    another: List[SomeParameters]

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

Output

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.