I'm trying to send JSON-data from an ESP32 via TCP to another client. This should happen repeatingly. The JSON-String contains an array. However, when I try to put an array in the JSON-document like in the example of the Arduino-documentation using the function createNestedArray(), it works for a few times until it starts creating empty arrays.
The minimal code is this:
#include "ArduinoJson.h"
StaticJsonDocument<3000> doc;
JsonObject root = doc.to<JsonObject>();
void insertJsonArray(JsonObject root) {
JsonArray arr = root.createNestedArray("arrValues");
arr.add(42);
arr.add(77);
}
void setup() {
Serial.begin(115200);
}
void loop() {
insertJsonArray(root);
// Print values
serializeJsonPretty(root, Serial);
// Print size of Json-Document
Serial.print("Json-Size: ");
Serial.println(root.memoryUsage());
delay(250);
}
The output looks like expected for the first 92 iterations:
{
"arrValues": [
42,
77
]
}
Json-Size: 48
But after that it only sends empty arrays:
{
"arrValues": []
}
Json-Size: 16
Has anybody an idea why it suddenly stops working at this point?
First of all, before talking about the problem, let's talk the capacity (i.e. size) of the json object required. If you use ArduinoJson Assistant, The json object
{
"arrValues": [
42,
77
]
}
would need about 58 bytes (with extra 10 bytes allocation for ESP32 as suggested by ArduinoJson Assistant), so your allocation of 3000 bytes to the doc
would waste of a lot memory, while 60 bytes would be sufficient for the purpose of your json object.
StaticJsonDocument<60> doc;
Now about the problem your described. You have a StaticJsonDocument doc
of 3000 bytes, and you are constantly inserting an JsonArray root
into the doc
, this is like appending the root
infinitely into the doc
, so it will sooner or later overflow. I don't see any reason why you need to do that constantly, if you need to create a json object in a loop, move the declaration of StaticJsonDocument
into your loop and create it when you need it.
void loop() {
StaticJsonDocument<60> doc;
JsonObject root = doc.to<JsonObject>();
JsonArray arr = root.createNestedArray("arrValues");
arr.add(42);
arr.add(77);
...
}
You can also use DynamicJsonDocument
instead of StaticJsonDocument
:
// use ArduinoJson Assistant tool to get the capacity
const size_t capacity = JSON_ARRAY_SIZE(2) + JSON_OBJECT_SIZE(1) + 20;
DynamicJsonDocument doc(capacity);
JsonObject root = doc.to<JsonObject>();
JsonArray arr = root.createNestedArray("arrValues");
arr.add(42);
arr.add(77);
ArduinoJson is a powerful library, but it requires a little bit better understanding of C++ capability in order to use it effectively, try to spend sometime to go through all the documentations.