Use String class in AsyncWebServerRequest

Beginner question:

I've read a lot about avoid String class due to memory fragmentation, so I tried to get rid of all references and usages. But for the code below I do not know how to do that. Could someone please point me in the right direction or is it safe to use the code like it is?

JsonDocument responseData;
String response;

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
  {
    responseData["Value"] = someValue; //someValue increases over time, like i++
    //String response; //do not use String class;
    serializeJson(responseData, response); //Use declared string
    request->send(200, "application/json", response);
  }
  );

I've come across SafeString Library but failed to use it here instead (too little knowledge).

I've declared response variable because I assume that if the variable is declared inside the {response} it will be created again and again for each response instead of created only once? Or is it ok to create "String response;" with each web request?

And does the increasing value (i) also lead to issues with the String class? This whole "avoid String class" thing confuses me a lot.

seems you are using ArduinoJSON. It uses dynamic memory allocation all over, so Strings should not worry you more than necessary (assuming you are on a ESP32).

that being said, if you want to only send someValue which is an integer, you don't need a JSON document for that...

on an esp just use .reserve() if needed and you are fine.

for this specific case (assuming someValue is an integer) I would not use ArduinoJSON nor the String class.

this would use up 30 bytes on the stack for the buffer

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    char response[30]; // make sure you have enough space
    // build the JSON answer
    snprintf(response, sizeof response, "{\"Value\": %d}", someValue);  // see https://cplusplus.com/reference/cstdio/snprintf/
    request->send(200, "application/json", response);
  }
);

you could use snprintf() returned value to ensure the whole JSON fitted in the buffer.


alternatively you can do it without any buffer at all in your code by printing to the underlying stream.

void handleRequest(AsyncWebServerRequest *request) {
  AsyncResponseStream *response = request->beginResponseStream("application/json");
  response->setCode(200);  // returned code for the response to say all went fine

  // Print directly to the response stream
  response->print("{\"value\": ");
  response->print(someValue);
  response->print("}");

  request->send(response);
}

server.on("/", HTTP_GET, handleRequest);

ArduinoJSON - yes.

Its more than just this one value which I added as example.

I basically have 2 "String" situations:

  1. deserializing a config.txt file from the LittleFS file system with a JSON. Contains around 20 variables.
  2. the example above, giving me some basic stats via a simple web request (like how often the device restarted, wifi disconnected..)

I use ESP8266 ESP-12F

ESP.getFreeHeap() returns around 40.000 constantly - is that an OK value or should I be worried? (Unfortunately I have not checked getFreeHeap before I removed most of String references)

that's plenty for 20 variables and their (short) labels.

Thanks