Describe the bug
Given the following OpenAPI yaml:
openapi: 3.0.0
components:
schemas:
InventoryItem:
type: object
properties:
item-id:
type: string
external-ids:
type: array
items:
type: string
oneOf:
- required: [ 'item-id' ]
- required: [ 'external-ids' ]
And the following generation commands:
datamodel-codegen --input inventory.yaml --input-file-type openapi --output inventory.py --output-model-type pydantic_v2.BaseModel
The resulted model is:
from __future__ import annotations
from typing import List, Optional, Union
from pydantic import BaseModel, Field, RootModel
class InventoryItem1(BaseModel):
item_id: str = Field(..., alias='item-id')
external_ids: Optional[List[str]] = Field(None, alias='external-ids')
class InventoryItem2(BaseModel):
item_id: Optional[str] = Field(None, alias='item-id')
external_ids: List[str] = Field(..., alias='external-ids')
class InventoryItem(RootModel[Union[InventoryItem1, InventoryItem2]]):
root: Union[InventoryItem1, InventoryItem2]
The following action fails:
>>> from inventory import InventoryItem
>>> InventoryItem(**{'item-id': '123'}).item_id
Traceback (most recent call last):
File "$PYDIR/site-packages/pydantic/main.py", line 761, in __getattr__
raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')
AttributeError: 'InventoryItem' object has no attribute 'item_id'
While the following succeeds:
>>> from inventory import InventoryItem
>>> InventoryItem(**{'item-id': '123'}).root.item_id
123
Or using the following generation command for pydantic v1 models
datamodel-codegen --input inventory.yaml --input-file-type openapi --output inventory.py
The resulted model is:
from __future__ import annotations
from typing import List, Optional, Union
from pydantic import BaseModel, Field
class InventoryItem1(BaseModel):
item_id: str = Field(..., alias='item-id')
external_ids: Optional[List[str]] = Field(None, alias='external-ids')
class InventoryItem2(BaseModel):
item_id: Optional[str] = Field(None, alias='item-id')
external_ids: List[str] = Field(..., alias='external-ids')
class InventoryItem(BaseModel):
__root__: Union[InventoryItem1, InventoryItem2]
The following action fails:
>>> from inventory import InventoryItem
>>> InventoryItem(**{'item-id': '123'}).item_id
Traceback (most recent call last):
"$PYDIR/site-packages/pydantic/_internal/_model_construction.py", line 92, in __new__
private_attributes = inspect_namespace(
File "$PYDIR/site-packages/pydantic/_internal/_model_construction.py", line 316, in inspect_namespace
raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'")
TypeError: To define root models, use `pydantic.RootModel` rather than a field called '__root__'
Expected behavior
Being able to access pydantic v2 model properties directly such as model.item_id
and not model.root.item_id
.
Version:
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too