Reputation: 3549
Can anyone explain me what that code snippet is doing to the output? Found here.
# Helper class to convert a DynamoDB item to JSON.
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if abs(o) % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)
Upvotes: 1
Views: 940
Reputation: 13791
DynamoDB has an unusual number type, described here, which is not the same as either int or double of most programming languages. I previously described DynamoDB's number type in Alternator's (Scylla's support for the DynamoDB API) documentation here:
Numbers in DynamoDB have an unusual definition - a non-standard floating-point representation with 38 decimal digits of precision and decimal exponent in the range -130 to +125 (see the official definition). Our encoding must not compromise these precision guarantees and in particular never cause rounding errors in a conversion to binary floating-point representation. Also, a “nice to have” is that integers and floating-point numbers with low precision take less space. Amazon indeed suggests (in the above link and in this discussion) that it uses variable-length encoding internally.
So as to faithfully represent DynamoDB's full range of numbers, the client library (boto3) represents them using a custom variable-precision type called "decimal", and this type is used in the library when it returns responses to the Python code.
The purpose of the code you quoted is to convert this special "decimal" type into the more familiar python types - int or float. It converts whole number numbers into ints, otherwise into float. Because (as explained above) the DynamoDB number type guarantees 38 decimal digits of precision, integers shorter than 38 decimal digits are guaranteed to be represented with full precision - so the check for whole numbers is always accurate.
Upvotes: 2