Description of the problem

You called serializeJson() or serializeJsonPretty() to generate a JSON document, but the result is incomplete.

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.

If it worked the first time and then starts to fail, that’s a different problem.

How to solve it?

Increase the capacity of the JsonDocument:

  • add JSON_OBJECT_SIZE(n) for each object of size n,
  • add JSON_ARRAY_SIZE(n) for each object of size n,
  • add n+1 for each string of n 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.

Use the ArduinoJson Assistant to compute the right capacity for your project.

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:

  1. How to deserialize a very large document?
  2. How to reduce memory usage?
  3. 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.