Decode a JSON number as Decimal for an amount field
Also published in our primary archive.
Decode a JSON number as Decimal for an amount field
To decode a JSON amount as Decimal, call json.loads(source, parse_float=Decimal). parse_float receives the numeric token as text, allowing Decimal to construct its value from "0.1" rather than from an already-rounded binary float.
This example starts with the exact JSON fixture {"amount":0.1}. With the default decoder, amount is a float; formatting its triple to 17 fractional places exposes the familiar binary representation result, 0.30000000000000004. That display is a property of this particular binary floating-point calculation, not proof that every float calculation is inappropriate.
The second decode sets parse_float=Decimal. Its assertions verify the two intended contract facts for this input: the field is Decimal('0.1'), and multiplying that decimal value by three equals Decimal('0.3'). The code leaves JSON integers on the default int path; if a contract also needs special integer handling, parse_int is a separate decoder option.
json.loads documents that its normal real-number conversion is float, while parse_float can use decimal.Decimal; Decimal supplies decimal fixed-point and floating-point arithmetic. See the official json documentation and decimal documentation. These APIs are long-standing standard-library interfaces; no newer-version-only API is used here. Choose precision, rounding, and validation rules separately when a domain requires them.
AI assistance disclosure: This article was drafted with AI assistance and verified with the synthetic fixture shown.
Example
import json
from decimal import Decimal
source = '{"amount":0.1}'
float_amount = json.loads(source)["amount"]
assert isinstance(float_amount, float)
print("float tripled:", format(float_amount * 3, ".17f"))
decimal_amount = json.loads(source, parse_float=Decimal)["amount"]
assert decimal_amount == Decimal("0.1")
assert decimal_amount * 3 == Decimal("0.3")
print("decimal:", repr(decimal_amount))
print("decimal tripled:", decimal_amount * 3)
Expected output:
float tripled: 0.30000000000000004
decimal: Decimal('0.1')
decimal tripled: 0.3