How to convert Decimal("123456789012345.99")
to json number 123456789012345.99?
Python 3.11 win64
import json
from decimal import Decimal
class DecimalToFloat(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return float(obj)
return json.JSONEncoder.default(self, obj)
class DecimalToStr(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return str(obj)
return json.JSONEncoder.default(self, obj)
obj = {'decimal':Decimal("123456789012345.99")}
# {"decimal": 123456789012345.98} - WRONG!!!!
print(json.dumps(obj, cls=DecimalToFloat))
# {"decimal": "123456789012345.99"} - json string
print(json.dumps(obj, cls=DecimalToStr))
# ??? {"decimal": 123456789012345.99}
UPD
simplejson module is OK
# {"decimal": 123456789012345.99}
print(simplejson.dumps(obj, use_decimal=True))
Is there a way to do the same with the standard library without external dependencies?
2
Answers
import json
from decimal import Decimal
d = Decimal("123456789012345.99")
s = str(d)
json_obj = {"number": s}
json_str = json.dumps(json_obj)
print(json_str) # outputs: {"number": "123456789012345.99"}
The issue you’re facing is due to the limitations of the float representation in Python, which uses double-precision floating-point numbers. The Decimal class, on the other hand, provides arbitrary-precision decimal arithmetic, which can handle large numbers and fixed decimal places accurately.
When you convert Decimal("123456789012345.99") to a float, the float representation cannot precisely represent the decimal number, leading to a small loss of precision. As a result, the float representation becomes 123456789012345.98.
To maintain the original decimal precision, you can use a custom JSON encoder that converts Decimal objects to strings:
By using the DecimalToStr JSON encoder, the Decimal object will be converted to its string representation, preserving the original decimal precision in the JSON output.
Keep in mind that when you use DecimalToStr, the decimal value will be represented as a string in the JSON output. If you need to use the number as a float in the JSON (e.g., for interoperability with other systems), you will encounter the inherent limitations of float representation, as shown in your initial code. In such cases, it’s generally better to keep the decimal as a string to avoid precision issues.