Callbacks to `Encoder`/`Decoder` are not respected in `datetime` objects
kaixuan-datature opened this issue · comments
Kai Xuan commented
Description
Both dec_hook
and enc_hook
arguments are not respected in all encoders and decoders (tested on JSON and YAML) when datetime
objects are used. Note that the print
functions in both hooks are not run, and the variable buf
contains an ISO 8601 duration string instead of a number (as seen from enc_hook
).
Attached is a sample script to show that custom decoding of datetime.timedelta
objects is not supported. It also doesn't work for datetime.datetime
objects.
import msgspec
from typing import Any, Type
from datetime import timedelta
def enc_hook(obj: Any) -> Any:
print("Encoding")
if isinstance(obj, timedelta):
# convert the timedelta to a number
return obj.total_seconds()
else:
# Raise a NotImplementedError for other types
raise NotImplementedError(f"Objects of type {type(obj)} are not supported")
def dec_hook(type: Type, obj: Any) -> Any:
print("Decoding", type)
# `type` here is the value of the custom type annotation being decoded.
if type is timedelta:
# Convert ``obj`` (which should be a ``number``) to a timedelta
return timedelta(seconds=obj)
else:
# Raise a NotImplementedError for other types
raise NotImplementedError(f"Objects of type {type} are not supported")
class MyMessage(msgspec.Struct):
field_1: str
field_2: timedelta
enc = msgspec.json.Encoder(enc_hook=enc_hook)
dec = msgspec.json.Decoder(MyMessage, dec_hook=dec_hook)
msg = MyMessage("some string", timedelta(seconds=5))
# Encode and decode the message to show that things work
buf = msgspec.yaml.encode(msg, enc_hook=enc_hook)
print(buf)
a = msgspec.yaml.decode(buf, type=MyMessage, dec_hook=dec_hook)
print(a)
Kai Xuan commented
Apologies, refer to the other issue instead