如何使用 pydantic 为数据类列表生成 JSON 模式?

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

我正在尝试从 python 数据 类 生成 JSON 架构,其中包含其他数据列表 类 作为参数。除了生成 json 模式之外,我真的不关心 pydantic 的任何功能,因为我只是使用输出来自动生成 Web 前端。所以使用其他库的解决方案很好。

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()

此代码有以下堆栈跟踪错误(您可以使用 SKIP_CYTHON=1 pip install --no-cache-dir --no-binary :all: pydantic 安装 pydantic 以便您可以对其进行调试):

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

现在根据JSON Schema documentation一组东西是有效的。 pydantic documentation 使用整数列表,这对我也适用。 我希望我也可以在列表中使用自定义类型。该文档进一步说明 Nested dataclasses are supported both in dataclasses and normal models.

我在做什么wrong/not我应该做什么吗?还是我误会了什么,这实际上是不允许的? 如果是这种情况,还有哪些替代方案?

有趣的是,您的代码在 Python 3.9.1 (Windows) 上对我有用。只是好奇,您使用的 pydantic 是什么版本?

这是适合我的代码。请注意,您可以使用 pydantic drop-in 数据类来稍微简化 JSON 模式生成。

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)

输出:

{'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'}}}}}

注意:我正在使用 pydantic==1.8.2

这是 pydantic 1.9 引入的错误。 我在这里贡献了一个解决这个问题的拉取请求: https://github.com/samuelcolvin/pydantic/pull/3819