You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We’re currently storing integer fields on objects in DynamoDB. DynamoDB/boto3 returns all numbers as Decimals – there is no dedicated integer type in DynamoDB. There doesn’t seem to be a convenient way to define integer fields on our Msgspec model classes and convert the Decimals into ints when converting to our model type.
I know there is lax mode, but we want to be strict for everything except parsing fields defined as int from Decimal.
I know we can define the field as float and use multiple_of=1, but float is not the correct type for us, code that uses the model classes should see ints.
I tried a decoding hook, but these only get called for unknown types, and Decimal is a known type.
Try this. I have a working solution for BigInteger which is represented as str when send in response and as int in python.
Converted my solution to fit your need. CAUTION: Not tested
from __future__ importannotationsfromdecimalimportDecimalfromtypingimportAny, SelfclassDint:
"""Decimal Int. iv = int value dv = decimal value """__slots__= ('iv', 'dv')
def__new__(cls, v: int|Decimal|Dint) ->Self:
self=object.__new__(cls)
ifvisNone:
self.iv, self.dv=None, Noneelifisinstance(v, Dint):
self.iv=v.ivself.dv=v.dvelifisinstance(v, int):
self.iv=vself.dv=Decimal(str(v))
elifisinstance(v, Decimal):
is_int=v.normalize().as_tuple().exponent>=0ifnotis_int:
raiseValueError("Invalid value for type int.")
self.iv=int(v)
self.dv=velse:
raiseTypeError(f"Expected int/Decimal/Dint. Got {type(v)}")
returnselfdef__bool__(self):
returnself.ivisnotNonedef_cmp(self, other):
ifotherisNone:
returnFalseifisinstance(other, Dint):
returnself.iv==other.ivifisinstance(other, Decimal):
returnself.dv==otherifisinstance(other, int):
returnself.iv==otherraiseTypeError(f"Unsupported other {other}")
def__eq__(self, other):
returnself._cmp(other)
def__ne__(self, other):
returnnotself._cmp(other)
def__int__(self):
returnself.ivdef__repr__(self):
returnf'Dint({self.iv})'def__str__(self):
returnf"{self.iv}"defdec_hook(t: type, o: Any) ->Dint:
"""Decode int represented as Decimal/int to Dint """iftisDint:
returnt(o)
raiseNotImplementedError(f"Objects of type {type(o)} are not supported.")
defenc_int_hook(o: Dint) ->int:
"""Encode Dint to int"""ifisinstance(o, Dint):
returno.ivraiseNotImplementedError(f"Objects of type {type(o)} are not supported.")
defenc_decimal_hook(o: Dint) ->int:
"""Encode Dint to decimal"""ifisinstance(o, Dint):
returno.dvraiseNotImplementedError(f"Objects of type {type(o)} are not supported.")
classMyClass(Struct, kw_only=True):
field1: Dint
Activity
zulqasar commentedon Apr 2, 2025
Try this. I have a working solution for BigInteger which is represented as str when send in response and as int in python.
Converted my solution to fit your need. CAUTION: Not tested