msgspec
msgspec copied to clipboard
Decimal should be handled as a custom type during demarshaling.
Hey!
I have a problem when I use msgspec and Decimal. One popular solution to using Decimal is to not round the data as part of the algorithm execution and business logic. The rounding happens during demarshaling at the API endpoints. Decimal is the native type, so it's not possible to create an Encoder that can handle this.
Is it possible to change the behaviour for Decimal and allow interception in enc_hook?
Example:
from decimal import ROUND_HALF_UP, Decimal
from typing import Any
import msgspec
def enc_hook(obj: Any) -> Any:
if isinstance(obj, Decimal):
return str(obj.quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP))
else:
raise NotImplementedError(f"Objects of type {type(obj)} are not supported")
class Price(msgspec.Struct):
primecost: Decimal
enc = msgspec.json.Encoder(enc_hook=enc_hook)
price = Price(primecost=Decimal("1.1234444"))
buf = enc.encode(price)
# b'{"primecost":"1.1234"}'
Creating a custom Decimal MyDecimal looks like a workaround.