bblanchon / ArduinoJson

📟 JSON library for Arduino and embedded C++. Simple and efficient.
https://arduinojson.org
MIT License
6.69k stars 1.12k forks source link

Base64 image string to json #2057

Closed AleksandarGT closed 6 months ago

AleksandarGT commented 7 months ago

Describe the bug
I am trying to serialize data into a json string, however the produced string in the end is not the same as the one I provided. The base64 string contains an image captured from ESP32-Cam. I have a similar problem as here #1105. While the provided solution makes sure that the JsonDocument does not overflow (using c_str), the produced output is not the same as the input.

Environment
Here is the environment that I used:

Reproduction
Here is a small snippet that reproduces the issue.

    String imageBase64 = captureAndSaveImage();

    jsonDocument.clear();
    jsonDocument["image"] = imageBase64.c_str();
    jsonDocument["email"] = "TestEmail";
    jsonDocument["deviceName"] = "MyDevice1";
    String jsonBody = "";

    Serial.println("Serializing");

    serializeJson(jsonDocument, jsonBody);
    Serial.println(imageBase64.substring(0, 50));

    const char *charPtr = imageBase64.c_str();

    for (int i = 0; i < 50 && charPtr[i] != '\0'; ++i)
    {
        Serial.print(charPtr[i]);
    }
    Serial.println("");
    Serial.println(jsonBody.substring(0, 50));

Expected output:

Serializing
/9j/4AAQSkZJRgABAQEAAAAAAAD/2wBDAAoHCAkIBgoJCAkLCw
/9j/4AAQSkZJRgABAQEAAAAAAAD/2wBDAAoHCAkIBgoJCAkLCw
{"image":"/9j/4AAQSkZJRgABAQEzSc1ou4vIYaTdS8wURxIN

Actual output:

Serializing
/9j/4AAQSkZJRgABAQEAAAAAAAD/2wBDAAoHCAkIBgoJCAkLCw
/9j/4AAQSkZJRgABAQEAAAAAAAD/2wBDAAoHCAkIBgoJCAkLCw
{"image":"/9j/4AAQSkZJRgABAQEAAAAAAAD/2wBDAAoHCAkIBgoJCAkLCw

As you can see the library modifies the base64 string at some point.

bblanchon commented 7 months ago

Hi @BoostedPenguin,

What does the ArduinoJson Troubleshooter say?

Best regards, Benoit

AleksandarGT commented 7 months ago

I can fix the overflow by following the Troubleshooter tips, however I cannot fix the garbage output string. If I hardcode a base64 string in the program itself, without capturing an image and then converting it to base64 the output string is correct. However, if I encode a captured image from the CAM it always produces garbage output.

Printing the value of the encoded string is always correct base64, but when I provide it to jsonDocument the output always goes wrong at a specific place:

/9j/4AAQSkZJRgABAQEAAAAAAAD /9j/4AAQSkZJRgABAQEr

`

JsonDocument jsonDocument;

Serial.println("Capturing image...");

camera_fb_t *fb = nullptr;

// Skip 3 frames :)
for (int i = 0; i < 5; i++)
{
    fb = esp_camera_fb_get();
    esp_camera_fb_return(fb);
    fb = nullptr;
}

fb = esp_camera_fb_get();

Serial.println("Captured");

if (!fb)
{
    return;
}

String encoded = base64::encode(fb->buf, fb->len);

Serial.println("Encoded...");
// Release the frame buffer
esp_camera_fb_return(fb);
Serial.println("Released");

Serial.println(encoded);
jsonDocument.clear();
jsonDocument["image"] = encoded;
jsonDocument["email"] = "TestEmail";
jsonDocument["deviceName"] = "MyDevice1";
String jsonBody;

jsonDocument.shrinkToFit(); // optional

Serial.println("Serializing");

serializeJson(jsonDocument, jsonBody);
Serial.println("Overflow: " + String(jsonDocument.overflowed()));

Serial.println(jsonBody.substring(0, 80));

Serial.println("Generating HTTP request");

`

bblanchon commented 7 months ago

If I hardcode a base64 string in the program itself, without capturing an image and then converting it to base64 the output string is correct. However, if I encode a captured image from the CAM it always produces garbage output.

This is the sign of a dangling pointer. What did the Troubleshooter say?