Reason 1: Null pointer dereferencing

Usually, a null pointer dereferencing happens when ArduinoJson returns a null whereas the program expects a string.

Here is an example:

char name[32];

JsonObject& obj = jsonBuffer.parseObject(input);
strlcpy(name, obj["name"], 32);

This program works fine, except when the value "name" is missing from the object, because obj["name"] return NULL. The same thing happens if parsing fails.

Here is how to fix this program:

char name[32];

JsonObject& obj = jsonBuffer.parseObject(input);
strlcpy(name, obj["name"] | "N/A", 32);

This snippet uses the | syntax introduced in ArduinoJson 5.12. It is equivalent to the following code:

char name[32];

JsonObject& obj = jsonBuffer.parseObject(input);

const char* jsonName = obj["name"];
if (jsonName)
  strlcpy(name, obj["name"], 32);
else
  strcpy(name, "N/A");

Reason 2: Stack-overflow

A stack overflow happens when you have too many variables in the “stack” memory.

Before reading further, make sure that your target platform does have enough RAM to store the JsonBuffer and possibly the JSON input too:

Once you’re sure that your device has enough RAM, you should move theJsonBuffer to the heap. Just replace your StaticJsonBuffer with a DynamicJsonBuffer.

If your JSON input is stored in the stack, you should move it to the heap too.

For instance, if you have a program like this:

char content[MAX_CONTENT_SIZE];
StaticJsonBuffer<JSON_BUFFER_SIZE> jsonBuffer;

receive(content);
JsonObject& root = jsonBuffer.parseObject(content);

Serial.println(root["name"].asString());

you should transform it like that:

char* content = malloc(MAX_CONTENT_SIZE);
DynamicJsonBuffer jsonBuffer(JSON_BUFFER_SIZE);

receive(content);
JsonObject& root = jsonBuffer.parseObject(content);

Serial.println(root["name"].asString());

free(content);

Reason 3: Incompatible configurations in compilation units

If your program behaves unpredictably, it may be because a different configuration is used in each .ino or .cpp file.

For example, imagine you have two files my_sketch.ino and my_lib.cpp.

The first file starts with:

// File: my_sketch.ino
#define ARDUINOJSON_USE_LONG_LONG 1
#include <ArduinoJson.h>

whereas the second starts with:

// File: my_lib.ino
#define ARDUINOJSON_USE_LONG_LONG 0
#include <ArduinoJson.h>

In that situation, the two compilation units have different sizes for JsonVariant. Since the linker is not able to detect this problem, it will create an executable with some functions using a big JsonVariant and others using small JsonVariant. The executable may work under some conditions but will crash sooner or later.

To fix this bug, you must use the same configuration in all compilation units. A simple way to do that is to share the configuration in a .h file.