You wrote a program that works fine for one or more iterations, but then fails?

Cause 1: reuse of JsonBuffer

First, this can happen if you reuse the same JsonBuffer, for example:

StaticJsonBuffer<200> jsonBuffer;

for (int i=0; i<10; i++) {
    char json[256];
    readJsonFromSomewhere(json, sizeof(json));

    JsonObject& root = jsonBuffer.parse(json);
    if (root.success()) {
       Serial.println("parseObject() succeeded");
    } else {
       Serial.println("parseObject() failed!");
    }
}

The solution is simply to NOT reuse the JsonBuffer, like this:

for (int i=0; i<10; i++) {
    char json[256];
    readJsonFromSomewhere(json, sizeof(json));

    StaticJsonBuffer<200> jsonBuffer;

    JsonObject& root = jsonBuffer.parse(json);
    if (root.success()) {
       Serial.println("parseObject() succeeded");
    } else {
       Serial.println("parseObject() failed!");
    }
}

Note that, contrary to common belief, moving a StaticJsonBuffer inside of a loop has no negative impact on performance.

Cause 2: reuse of JSON input

This second case only concerns the “zero-copy” mode. This mode is selected when the input is writable (char[] or a char*). In this mode, ArduinoJson modifies the input string in place: it inserts null terminators and unescapes special characters. If you call parseObject() twice with the same input buffer, the first will work, but the second will fail because the input buffer doesn’t contain a valid JSON document anymore.

Here is a program that has this problem:

char json[256];
readJsonFromSomewhere(json, sizeof(json));

for (int i=0; i<10; i++) {
    StaticJsonBuffer<200> jsonBuffer;

    JsonObject& root = jsonBuffer.parse(json);
    if (root.success()) {
       Serial.println("parseObject() succeeded");
    } else {
       Serial.println("parseObject() failed!");
    }
}

The solution is simply to parse the input only once, or get a fresh input at each iteration:

for (int i=0; i<10; i++) {
    char json[256];
    readJsonFromSomewhere(json, sizeof(json));

    StaticJsonBuffer<200> jsonBuffer;

    JsonObject& root = jsonBuffer.parse(json);
    if (root.success()) {
       Serial.println("parseObject() succeeded");
    } else {
       Serial.println("parseObject() failed!");
    }
}

If you don’t want ArduinoJson to modify the input buffer, e.e. if you want to disable the zero-copy mode, you need to pass the input as a read-only type, like const char*:

char json[256];
readJsonFromSomewhere(json, sizeof(json));

for (int i=0; i<10; i++) {
    StaticJsonBuffer<400> jsonBuffer;

    JsonObject& root = jsonBuffer.parse((const char*)json);
    if (root.success()) {
       Serial.println("parseObject() succeeded");
    } else {
       Serial.println("parseObject() failed!");
    }
}

In this case, you also need to increase the capacity of the JsonBuffer because it will have to hold a partial copy of the input. As usual, use the Assistant to compute the optimal capacity.

See also