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 size n,
  • add JSON_OBJECT_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.

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
  • Arduino UNO
  • Arduino UNO WiFi
  • Arduino Nano
  • Adafruit Metro Mini 328
  • SparkFun RedBoard
ATmega32u4 2.5 KB
  • Arduino Leonardo
  • Arduino Micro
  • Adafruit Feather 32u4 Bluefruit LE
  • Arduino Yún
  • Teensy 2.0
ATMega4809 6 KB
  • Arduino Nano Every
  • Arduino UNO WiFi Rev 2
ATmega2560 8 KB
  • Arduino Mega 2560
AT90USB1286 8 KB
  • Teensy++ 2.0
MKL26Z64VFT4 8 KB
  • Teensy LC
MK20DX256VLH7 64 KB
  • Teensy 3.2
ESP8266 96 KB
  • Adafruit HUZZAH
  • SparkFun ESP8266 Thing
  • WeMos D1 Mini
MK64FX512 192 KB
  • Teensy 3.5
MK66FX1M0 256 KB
  • Teensy 3.6
ESP32 520 KB
  • Adafruit HUZZAH32
  • LoLin D32 Pro
i.MX RT1066 1 MB
  • Teensy 4.0

Some ESP32s come with a large external PSRAM that you can use with ArduinoJson.

Global warming stripes by Professor Ed Hawkins (University of Reading)