Adds a new `dec_hook` callback supporting type conversions between
builtin msgpack types and arbitrary python types. This hook should have
the following signature:
```python
def dec_hook(obj: Any, type: Type) -> Any:
...
```
This receives an object composed of builtin msgpack types (e.g. dict,
list, int, ...) and the expected decode type (as described by the
decoder's type parameter). It should attempt to convert the value to the
provided type, or raise a type error appropriately. When combined with
`enc_hook` on the encoder, this lets users serialize arbitrary custom
objects without resorting to extension types.
For example, to serialize/deserialize a `NamedTuple` you might write
the following:
```python
import msgspec
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
def enc_hook(obj):
if isinstance(obj, tuple):
# convert the named tuple to a supported type
# in this case it's a tuple like `(1, 2)`
return tuple(obj)
raise TypeError(f"Type {type(obj).__name__} is not supported")
def dec_hook(obj, type):
if issubclass(type, tuple):
# convert the builtin type (e.g. `[1, 2]`) to
# the custom type (`Point(x=1, y=2)`)
return type(*obj)
raise TypeError(f"Type {type.__name__} is not supported")
enc = msgspec.Encoder(enc_hook=enc_hook)
dec = msgspec.Decoder(Point, dec_hook=dec_hook)
msg = enc.encode(Point(1, 2))
x = dec.decode(msg)
print(x) # Point(x=1, y=2)
```