Description

The macro ARDUINOJSON_ENABLE_PROGMEM enables the support of Flash strings in ArduinoJson. Unlike regular strings, Flash strings are not present in the RAM; they only reside in the Flash memory alongside the program (“progmem” stands for “program memory”).

This feature only makes sense on Harvard architectures (mainly AVR and ESP8266).
It’s useless on von Neumann architectures (such as ESP32, megaAVR, and ARM).

The default value of ARDUINOJSON_ENABLE_PROGMEM is 1 if the following macros are defined:

  • PROGMEM
  • pgm_read_byte
  • pgm_read_dword
  • pgm_read_ptr
  • pgm_read_float

In other words, ArduinoJson supports Flash strings as soon as all the required macros are defined.

Only 0 and 1 are valid. Any other value (like false or true) will produce a compilation error.

How to force the value?

If you need to force the support of Flash strings, add this at the top of your program:

#define ARDUINOJSON_ENABLE_PROGMEM 1
#include <ArduinoJson.h>

On the other hand, if you need to disable Flash strings, do:

#define ARDUINOJSON_ENABLE_PROGMEM 0
#include <ArduinoJson.h>

Disabling the support of Flash string is useful if your platform defines PROGMEM but doesn’t fully support Flash strings; for example, if you get the following error:

.../src/ArduinoJson/Polyfills/pgmspace_generic.hpp:14:10: error: reinterpret_cast from 'const void' to 'const __FlashStringHelper *' is not allowed
  return reinterpret_cast<T>(pgm_read_ptr(p));
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Several .ino or .cpp files?

Be careful if several compilation units compose your program, i.e., if your project contains several .ino or .cpp files.

You should define the same value of ARDUINOJSON_ENABLE_PROGMEM in each compilation unit; otherwise, the executable will be much bigger because it will contain two variants of the library.

Where ArduinoJson supports Flash strings?

Once enabled, you can use a Flash string in many places.

  1. You can use a Flash string as your JSON input

     // WARNING: ArduinoJson duplicates the string in the JsonDocument
     deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
                            "\"data\":[48.756080,2.302038]}"));
    
  2. You can use a Flash string to get an element of a JsonObject

     long time = root[F("time")];
    
  3. You can use a Flash string to set an element of a JsonObject

     // WARNING: ArduinoJson duplicates the string in the JsonDocument
     root[F("time")] = time;
    
  4. You can set a JsonObject (or JsonArray) element to a Flash string:

     // WARNING: ArduinoJson duplicates the string in the JsonDocument
     root["sensor"] = F("gps");
    
  5. You can compare the content of a JsonObject with a Flash string

     if (root["sensor"] == F("gps")) {
         // ...
     }
    
Gotcha ⚠️

ArduinoJson relies on the type const __FlashStringHelper* to detect if a string is in Flash.

If you use the F() macro as above, you don’t have to worry about it. However, if you use a char[] with the PROGMEM attribute, you must cast the pointer before passing it to ArduinoJson. Here is an example:

const char myValue[] PROGMEM = "hello world";
root["message"] = (const __FlashStringHelper*)myValue;

This gotcha is not limited to ArduinoJson; many Arduino functions, like Serial.println(), need this cast too.

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