Pydantic与含oneOf的JSON Schema兼容问题:缺失field_1字段
问题:datamodel-codegen生成Pydantic模型时丢失field_1字段
我尝试基于包含oneOf关键字的JSON Schema生成Pydantic模型,Schema内容如下:
{ "$schema": "https://json-schema.org/draft/2019-09/schema", "type": "object", "title": "v2_test", "additionalProperties": true, "oneOf": [ { "type": "object", "properties": { "field_1": { "enum": [ "response_1" ] } }, "additionalProperties": true, "oneOf": [ { "type": "object", "properties": { "field_2": { "enum": [ "response_a" ] } }, "additionalProperties": true, "required": [ "field_2" ] } ], "required": [ "field_1" ] }, { "type": "object", "properties": { "field_1": { "enum": [ "response_2" ] } }, "additionalProperties": true, "oneOf": [ { "type": "object", "properties": { "field_2": { "enum": [ "response_b" ] } }, "additionalProperties": true, "required": [ "field_2" ] }, { "type": "object", "properties": { "field_2": { "enum": [ "response_c" ] } }, "additionalProperties": true, "required": [ "field_2" ] } ], "required": [ "field_1" ] } ] }
使用命令datamodel-codegen --input schema.json --input-file-type jsonschema --output model.py生成后,模型代码丢失了Schema要求的field_1字段(枚举值为response_1或response_2),生成的代码如下:
# generated by datamodel-codegen: # filename: v2_differnet_names_schema.json # timestamp: 2022-08-21T09:12:26+00:00 from __future__ import annotations from enum import Enum from typing import Union from pydantic import BaseModel, Extra, Field class Field2(Enum): response_a = 'response_a' class V2TestItem(BaseModel): class Config: extra = Extra.allow field_2: Field2 class Field21(Enum): response_b = 'response_b' class V2TestItem1(BaseModel): class Config: extra = Extra.allow field_2: Field21 class Field22(Enum): response_c = 'response_c' class V2TestItem2(BaseModel): class Config: extra = Extra.allow field_2: Field22 class V2Test(BaseModel): class Config: extra = Extra.allow __root__: Union[V2TestItem, Union[V2TestItem1, V2TestItem2]] = Field( ..., title='v2_test' )
解决方案
方法1:手动修正生成的模型代码
直接在生成的各个Item模型中添加field_1字段及对应枚举,确保field_1的枚举值与field_2匹配:
from __future__ import annotations from enum import Enum from typing import Union from pydantic import BaseModel, Extra, Field class Field1(Enum): response_1 = 'response_1' response_2 = 'response_2' class Field2(Enum): response_a = 'response_a' class V2TestItem(BaseModel): class Config: extra = Extra.allow field_1: Field1 = Field(Field1.response_1) field_2: Field2 class Field21(Enum): response_b = 'response_b' class V2TestItem1(BaseModel): class Config: extra = Extra.allow field_1: Field1 = Field(Field1.response_2) field_2: Field21 class Field22(Enum): response_c = 'response_c' class V2TestItem2(BaseModel): class Config: extra = Extra.allow field_1: Field1 = Field(Field1.response_2) field_2: Field22 class V2Test(BaseModel): class Config: extra = Extra.allow __root__: Union[V2TestItem, Union[V2TestItem1, V2TestItem2]] = Field( ..., title='v2_test' )
方法2:调整JSON Schema结构,优化兼容性
datamodel-codegen对嵌套oneOf的解析存在局限性,可将Schema中的嵌套oneOf合并为顶层的oneOf,明确每个分支的完整字段要求:
{ "$schema": "https://json-schema.org/draft/2019-09/schema", "type": "object", "title": "v2_test", "additionalProperties": true, "oneOf": [ { "type": "object", "properties": { "field_1": { "enum": ["response_1"] }, "field_2": { "enum": ["response_a"] } }, "additionalProperties": true, "required": ["field_1", "field_2"] }, { "type": "object", "properties": { "field_1": { "enum": ["response_2"] }, "field_2": { "enum": ["response_b"] } }, "additionalProperties": true, "required": ["field_1", "field_2"] }, { "type": "object", "properties": { "field_1": { "enum": ["response_2"] }, "field_2": { "enum": ["response_c"] } }, "additionalProperties": true, "required": ["field_1", "field_2"] } ] }
使用同样的datamodel-codegen命令重新生成,此时生成的模型会包含完整的field_1和field_2字段。
方法3:升级工具或启用特定参数
如果使用的是旧版本的datamodel-codegen,先升级到最新版本:
pip install --upgrade datamodel-codegen
或者添加--use-subclass参数,帮助工具更好地处理嵌套的oneOf结构:
datamodel-codegen --input schema.json --input-file-type jsonschema --output model.py --use-subclass
内容的提问来源于stack exchange,提问作者Cole
相关产品推荐
相关产品推荐

