Repository navigation
Open
Description
Related Issues
#671 ("Support adding hooks for supported objects types") - Similar request for overriding native type handling.
#766, #669, #671
Description
When using msgspec.convert with structs, certain built-in types (like datetime, date, etc.) are handled automatically and bypass the dec_hook. This forces developers to create artificial subclasses of native types just to get custom decoding behavior.
Problem Example
Current Workaround (Artificial Subclasses Required)
from datetime import date, datetime
from typing import Any, Type
import msgspec
# Required wrapper classes to bypass built-in handling
class CustomDate(date):
"""Workaround to handle date strings like 'DD/MM/YYYY'"""
pass
class CustomDatetime(datetime):
"""Workaround to handle ISO datetime strings"""
pass
def dec_hook(type_: Type, obj: Any) -> Any:
# Custom parsing only works through wrapper classes
if type_ is CustomDate:
if isinstance(obj, str):
day, month, year = map(int, obj.split('/'))
return CustomDate(year, month, day)
if type_ is CustomDatetime:
if isinstance(obj, str):
return CustomDatetime.fromisoformat(obj)
raise NotImplementedError(f"Unsupported type: {type_}")
class Event(msgspec.Struct):
# Forced to use non-standard types
start: CustomDatetime
end: CustomDatetime | None
registration_deadline: CustomDate
# Usage requires wrapper types
event = msgspec.convert(
{"start": "2024-01-01T12:00:00", ...},
Event,
dec_hook=dec_hook
)Problems This Creates:
- ❌ Artificial type hierarchy pollution
- ❌ Inconsistent with standard library types
- ❌ Extra boilerplate for common use cases
- ❌ Type checker complications
Proposed Solution
New API Usage
msgspec.convert(
data,
cls,
dec_hook=custom_handler,
disable_builtin_types={datetime, date} # New parameter
)Implementation Benefits:
- ✅ Uses standard types directly
- ✅ Explicit opt-in/opt-out control
- ✅ Maintains backward compatibility
- ✅ Clean integration with type checkers
Example Improvement:
def dec_hook(type_: Type, obj: Any) -> Any:
# Direct native type handling
if type_ is date:
return parse_custom_date(obj) # Implement your format
if type_ is datetime:
return parse_custom_datetime(obj)
class Event(msgspec.Struct):
# Uses proper standard types
start: datetime
end: datetime | None
deadline: dateTechnical Considerations
- Would work alongside existing
builtin_typesparameter - Should support all currently auto-converted types:
datetime,date,time,timedeltaUUID,Decimalbytes,bytearray
Reacted by 叶子, Jacopo Abramo, Clint Valentine, PanagiotisS, cswimr, Максим Заикин, dhirschfeld-ffma, Jiří Kuneš, Jacob, miniwark and 2 more
Reacted by 叶子 and Clint Valentine
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]Add an option to exclude builtin_types auto decoding from msgspec.convert[/-][+]Allow bypassing built-in type conversion in `msgspec.convert` via dec_hook[/+]clintval commentedon Jun 10, 2025
Or have
dec_hookrun prior to the builtin conversion, but yes I want this too!JimDabell commentedon Aug 4, 2025
#829 is also an issue that would be solved by this.
oelhammouchi commentedon Feb 24, 2026
Is there any progress on this?