When using tagged unions, while the correct OpenAPI schema is generated, decoding the request fails. It also doesn't work with the MsgpackDTO. It seems that the internal litestar.typing.FieldDefinition type doesn't support tagged unions.
A question thou, are tagged unions meant to be supported in litestar? I would be happy to contribute to fix/implement the solution if it's meant to be there.
No response
from typing import Annotated, Literal
from litestar import Controller, Litestar, post
from litestar.contrib.pydantic import PydanticDTO
from pydantic import BaseModel, Field
class DataA(BaseModel):
name: str
type: Annotated[Literal["A"], Field("A")]
class DataB(BaseModel):
name: str
type: Annotated[Literal["B"], Field("B")]
class DataContainer(BaseModel):
value: Annotated[DataA | DataB, Field(discriminator="type")]
class TaggedUnionExample(Controller):
dto = PydanticDTO[DataContainer]
@post("/data/")
def post_data(self, data: DataContainer) -> str:
return data.value.name
app = Litestar(route_handlers=[TaggedUnionExample])
1. `LITESTAR_APP=example:app litestar run --debug`
2. `echo '{"value": {"type": "B", "name": "test"}}' | http post http://localhost:8000/data/`
4. See error
"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"
Traceback (most recent call last):
File ".../.venv/lib/python3.12/site-packages/litestar/middleware/exceptions/middleware.py", line 219, in __call__
await self.app(scope, receive, send)
File ".../.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 82, in handle
response = await self._get_response_for_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 134, in _get_response_for_request
return await self._call_handler_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 154, in _call_handler_function
response_data, cleanup_group = await self._get_response_data(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 178, in _get_response_data
data = await kwargs["data"]
^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/_kwargs/extractors.py", line 490, in dto_extractor
return data_dto(connection).decode_bytes(body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py", line 100, in decode_bytes
return super().decode_bytes(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/dto/base_dto.py", line 97, in decode_bytes
return backend.populate_data_from_raw(value, self.asgi_connection)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/dto/_codegen_backend.py", line 144, in populate_data_from_raw
return self._transfer_to_model_type(self.parse_raw(raw, asgi_connection))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/dto/_backend.py", line 237, in parse_raw
result = decode_json(value=raw, target_type=self.annotation, type_decoders=type_decoders)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../.venv/lib/python3.12/site-packages/litestar/serialization/msgspec_hooks.py", line 183, in decode_json
return msgspec.json.decode(
^^^^^^^^^^^^^^^^^^^^
TypeError: If a type union contains multiple Struct types, all Struct types must be tagged (via `tag` or `tag_field` kwarg) - type `typing.Annotated[typing.Union[litestar.dto._backend.PostDataDataContainer_0DataARequestBody, litestar.dto._backend.PostDataDataContainer_1DataBRequestBody], msgspec.Meta(examples=[])]` is not supported
2.8.2
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