How does ArduinoJson serialize floats?

When you call serializeJson(), ArduinoJson converts each floating point value into a string with a variable number of decimal places. This behavior differs from Serial::print() which uses a fixed number of decimal places.

ArduinoJson uses as few digits as possible: it doesn’t add trailing zeros. It uses up to 9 decimal places; this is a limitation of the lightweight float-to-string algorithm.

When the value is very large (above 1e7), ArduinoJson switches to the scientific notation and adds an exponent to the value. It uses the same notation if the value is very small (below 1e-5).

Here are some examples:

Original value JSON output Explanation
3.14 "3.14"  
3.14159265359 "3.141592654" Only 9 decimal places
1.0 "1" No trailing zeros
0.9999999999 "1" Rounding
10000000.0 "1e7" Exponentiation
0.00001 "1e-5" Exponentiation

How to reduce the number of decimal places?

If you find that there are too many digits, you can round the floating point value. Use the function below to have a maximum of two decimal places.

// rounds a number to 2 decimal places
// example: round(3.14159) -> 3.14
double round2(double value) {
   return (int)(value * 100 + 0.5) / 100.0;

How to add trailing zeros?

If you need to get the trailing zeros, you need to bypass ArduinoJson’s conversion algorithm with serialized().

Fortunately, you don’t have to implement your own algorithm; you can reuse the one implemented in Arduino’s String, which uses a fixed number of decimal places:

doc["value"] = serialized(String(1.0,6)); // 1.000000

How to disable exponentiation?

It’s possible to tweak the conversion by changing the following settings:

These two settings give some margin but don’t allow disabling the scientific notation entirely. If you want to disable it, you need to bypass ArduinoJson’s conversion algorithm with serialized().

doc["value"] = serialized(String(1e9)); // 1000000000