Niraj Zade | Website is a work in progress.

Representing financial amounts in API's JSON

2024 Nov 04  |  3 min read  |  tags: api-design 1 json 1


The problem

JSON only supports float values as per the IEEE-754 standard. And IEEE 754 standard is terrible for representing most floats.

Here is a classic example:

>> 0.1+0.2
0.30000000000000004

The fundamental reason is simple - financial numbers are in powers of 10 (decimal), computer-stored numbers are in powers of 2 (binary). Powers of 2 cannot be used to accurately represent powers of 10, so there is always some rounding and some inaccuracy.

As a rule of thumb, don't use JSON to send fractional values. You can use JSON for floats only if:

For financial APIs, IEEE-754 is not at all okay. The standard cannot represent fractional values properly. So, it cannot represent fractional amounts like $0.1. And your amounts are going to be fractional most of the time

Solution

The solution is simple - get rid of the float data type from your JSON, and only use integer or string datatypes in the JSON-communication layer.

Look at the financial APIs around you. They are all using integer or string in their JSON.

In case you find float in a financial API's JSON, you're looking at an API that is going to cause inaccuracies.

HOW TO DO IT?

Convert everything into int or string during communication, to prevent loss of information due to limited precision of the IEEE-754 float.

Converting the amount into an integer is almost an industry standard. To do it, represent the amount in its currency's lowest denomination. Examples:

Then, after receiving the JSON, convert the amount back into whatever appropriate datatype is supported in your application's language (Usually Decimal/Numeric/BigInt).


If you are wondering what is needed for accurately processing and storing financial numbers, or fractional numbers in general , here are 2 solutions:

And from experience, and after talking to too many people about this during the 2021-2022 period, just store money as integer in the smallest denomination. If you really need floats, decimal datatype with 4 decimal digits will solve most use cases (the internet favourite is DECIMAL(19, 4)).

And on an ending note, IEEE 754's limitation is the reason why I cannot fathom why there are companies writing financial APIs in javascript (Node JS). That language has only one numeric datatype - double precision float (IEEE 754). Doesn't even have int!

Table Of Contents:

All Articles

Blog

Resources