Support Literal[bool]
Description
Many APIs use something like {"success": true, data: ...}.
It will be really nice to be able to validate such boolean field against constant value when deserializing:
from typing import Literal
import msgspec
class ResponseData(msgspec.Struct):
pass
class Response(msgspec.Struct):
success: Literal[True]
data: ResponseData
response = msgspec.convert(
{
"success": True,
"data": {},
},
Response,
)
At the moment this raises:
TypeError: Literal may only contain None/integers/strings - typing.Literal[True] is not supported
Thank you 👍
why not just use bool directly?
class Response(msgspec.Struct):
success: bool
data: ResponseData
EDIT: I don't really see the point in using a literal for a boolean; perhaps there's a reason for when an API always sets a response to True, but then again using bool should be more than enough
Using post-init-processing could help here https://jcristharif.com/msgspec/structs.html#post-init-processing
class Response(msgspec.Struct):
success: bool
data: ResponseData
def __post_init__(self):
if self.success is not True:
raise ValueError("Expected success==true")
And if success is False, you'd rather get a validation error from msgspec? I'd find that misleading
I'm coming straight from pydantic v2, in which I was able to model api response like this:
class ApiResponseOk(BaseModel):
success: Literal[True]
data: SomeDataModel
class ApiResponseError(BaseModel):
success: Literal[False]
errors: list[ApiResponseErrorItem]
ApiResponse = RootModel[ApiResponseOk | ApiResponseError]
I understand that msgspec does not allow to create union types, like in pydantic.
And if
successis False, you'd rather get a validation error from msgspec? I'd find that misleading
If i receive error response I will then get "data field not found" error from msgspec, which is even worse then something like "expected success to be True, but is False".
I assumed this would be easy, as we already have string and numeric literals.