Библиотека ArduinoJson: сколько места выделить для сериализованного буфера?

Я использую великолепную библиотеку ArduinoJson для работы с данными JSON на моем ESP8266. Я сталкивался с проблемами случайного программного сброса wdt и исследовал утечки памяти везде, где только мог. Я хочу максимально сократить использование Strings и DynamicJsonDocument. Поэтому я подумал об использовании автоматических переменных: буферов символов: char[N] и StatitcJsonDocument.

Я использую ассистент ArduinoJson, чтобы определить, сколько байт мне следует зарезервировать. Ниже приведены полезные данные одного ответа, которые я ожидаю получить:

// ввод символов[MAX_INPUT_LENGTH];

StaticJsonDocument<128> doc;

DeserializationError error = deserializeJson(doc, input, MAX_INPUT_LENGTH);

if (error) {
  Serial.print(F("deserializeJson() failed: "));
  Serial.println(error.f_str());
  return;
}

int statusCode = doc["statusCode"]; // 200
bool needUpdate = doc["needUpdate"]; // истинный
const char* message = doc["message"]; // "требуется обновление"

JsonObject data = doc["data"];
const char* data_deviceId = data["deviceId"]; // "DLD00005"
const char* data_user_fw_version = data["user_fw_version"]; // "0.0.0quot;
const char* data_new_fw_version = data["new_fw_version"]; // "0.0.5quot;

Как вы можете видеть, я использую тип char [N] в качестве входных данных, который фактически копируется с помощью strncpy() из https .getString().c_str() из ответа на предыдущий запрос https.POST(). Моя проблема в том, что я не знаю, сколько памяти мне следует зарезервировать для массива char[N], т.е. каким должно быть значение N? Причина, по которой я спрашиваю, заключается в том, что я получаю ошибку deserialization(): IncompleteInput, что, я почти уверен, связано с тем, что буфер char[N] недостаточно велик. . Итак, мой вопрос: если объект StaticJsonDocument имеет размер 128 байт, то какого размера мне следует сделать буфер char[N] (есть ли какая-либо связь между размерами)? Или мне следует просто использовать произвольно большое значение, например char[512], которого я хочу избежать, чтобы избежать переполнения стека?

StaticJsonDocument<128> payload;
char payloadSerial[???];  
...
int status = https.POST(payloadSerial);
strncpy(payloadSerial, https.getString().c_str(), sizeof(payloadSerial));
DeserializationError error = deserializeJson(payload, payloadSerial, sizeof(payloadSerial));
if (error) {
    Monitor.print(F("DeserializeJson() failed: "));
    Monitor.println(error.f_str());
}

, 👍1


1 ответ


2

Вы спрашиваете о коде, который выглядит следующим образом:

StaticJsonDocument<128> payload;
char payloadSerial[???];  
...
int status = https.POST(payloadSerial);
strncpy(payloadSerial, https.getString().c_str(), sizeof(payloadSerial));
DeserializationError error = deserializeJson(payload, payloadSerial, sizeof(payloadSerial));

Документация для deserializeJson() показывает, что это может принимать String напрямую:

DeserializationError deserializeJson(JsonDocument& doc, const String& input);

Поэтому нет необходимости копировать https.getString().c_str() в payloadSerial. Вы можете просто передать String, который возвращает https.getString():

StaticJsonDocument<128> payload;

int status = https.POST(request_body);

DeserializationError error = deserializeJson(payload, https.getString());

Вы использовали здесь один и тот же массив символов как для тела запроса, который вы передали в POST(), так и для десериализации ответа JSON. Хотя это нормально, для ясности я изменил вызов POST, чтобы использовать что-то другое, поскольку массив символов совершенно не нужен для обработки ответа.

Даже если deserializeJson() не принял тип String в качестве аргумента, вам все равно не потребуется копировать ответ в буфер. Вы можете просто передать https.getString().c_str():

StaticJsonDocument<128> payload;

int status = https.POST(request_body);

DeserializationError error = deserializeJson(payload, https.getString().c_str());

Вам действительно следует проверить значение status. Он указывает, прошел ли POST успешно или нет. Если это не удалось, вам следует сообщить об этом и указать причину сбоя, а не пытаться обрабатывать возвращенные полезные данные, поскольку возвращенных полезных данных нет.

,