Why is the output incomplete?
Description of the problem
You called serializeJson()
or serializeJsonPretty()
to generate a JSON document, but some parts are missing.
For example, you wanted to write {"values":[0,1]}
, but instead you got {"value":[]}
or even {}
.
Or maybe you wanted to write {"hello":"world"}
, but got {"hello":null}
.
That’s because the JsonDocument
is too small: it doesn’t have enough room to store the complete tree.
You can quickly diagnose this issue by looking at the result of JsonDocument::overflowed()
.
If it’s true
, then the JsonDocument
was too small, so it had to drop some values.
If it worked the first time and then starts to fail, that’s a different problem.
How to solve it?
To solve this issue, you need to increase the capacity of the JsonDocument
.
Most of the time, you can use the ArduinoJson Assistant to compute the capacity suitable for your project.
If you want to manually compute the capacity, here is how to proceed:
- add
JSON_ARRAY_SIZE(n)
for each array of sizen
, - add
JSON_OBJECT_SIZE(n)
for each object of sizen
, - add
n+1
for each string ofn
characters.
You only need to include strings of type char*
, String
, and Flash strings because ArduinoJson copies them in the JsonDocument
.
You don’t need to count const char*
and strings literals because ArduinoJson only stores a pointer.
What happens if the capacity is too large?
On the one hand, the JsonDocument
must be large enough to store your data; but on the other hand, it must be small enough to fit in the RAM of the microcontroller.
StaticJsonDocument
When a StaticJsonDocument
is too large, it causes a stack overflow. Your program enters the dark realm of undefined behavior: the program may run fine for a while and suddenly fail for inexplicable reasons. So be reasonable with the size of a StaticJsonDocument
.
Some platforms limit stack (e.g., 4 KB on the ESP8266, 8 KB on ESP32), so consider switching to a DynamicJsonDocument
if your StaticJsonDocument
becomes large.
DynamicJsonDocument
DynamicJsonDocument
calls malloc()
in its constructor to allocate the memory pool.
If this allocation fails, the DynamicJsonDocument
has no memory pool and cannot store anything except the root value.
In other words, if you try to create a huge memory pool, you may end up without any memory pool at all!
In this situation, JsonDocument::capacity()
returns 0
, and serializeJson()
outputs a empty object ({}
), a empty array ([]
) or null
.
What if my microcontroller is too small?
If the JsonDocument
is too large to fit in RAM, see:
- How to deserialize a very large document?
- How to reduce memory usage?
- How to use external RAM on an ESP32?
If none of these suggestions works for your project, you’ll have to purchase a larger microcontroller. The table below shows the most common microcontrollers and boards ordered by RAM capacity.
Microcontroller | RAM capacity | Boards |
---|---|---|
ATmega328 | 2 KB | |
ATmega32u4 | 2.5 KB | |
ATMega4809 | 6 KB | |
ATmega2560 | 8 KB | |
AT90USB1286 | 8 KB | |
MKL26Z64VFT4 | 8 KB | |
MK20DX256VLH7 | 64 KB | |
ESP8266 | 96 KB | |
MK64FX512 | 192 KB | |
MK66FX1M0 | 256 KB | |
ESP32 | 520 KB | |
i.MX RT1066 | 1 MB |
Some ESP32s come with a large external PSRAM that you can use with ArduinoJson.