What’s the problem?

Suppose that you wrote the following program:

const size_t capacity = JSON_OBJECT_SIZE(1)
StaticJsonDocument<capacity> doc;

doc["hello"] = "world";

serializeJson(doc, Serial);

If you look that the Serial Monitor, you’ll find that the program prints the following lines, as expected:

{"hello":"world"}

However, if you change the program to use a String, like so:

doc["hello"] = String("world");

Then, the program doesn’t produce the expected output anymore.
Instead, you see the following:

{"hello":null}

The same problem happens if you use a Flash string, like so:

doc["hello"] = F("world");

Why does this happen?

When you insert a string value in a JsonDocument, ArduinoJson behaves differently depending on the type of the string:

  • If it’s a const char* (for example, a string literal, like "world"), it stores a pointer.
  • For any other type (for example, a String instance or a Flash string), it stores a copy.

The copy of the string goes into the memory pool of the JsonDocument. If the memory pool cannot hold a copy of the string, ArduinoJson replaces it with null.

How to solve this problem?

To fix this problem, you must increase the capacity of the JsonDocument.

Simply add the required number of bytes (or an estimation), to the capacity:

const size_t capacity = JSON_OBJECT_SIZE(1) + 16

Note that the ArduinoJson shows the required number of bytes under the label “Additional bytes for strings duplication”.

See also

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