diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index 2bd8112255..7e701af48b 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -26,21 +26,33 @@ std::string build_json(const json_build_t &f) { const size_t free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); #endif - const size_t request_size = std::min(free_heap, (size_t) 512); - - DynamicJsonDocument json_document(request_size); - if (json_document.capacity() == 0) { - ESP_LOGE(TAG, "Could not allocate memory for JSON document! Requested %u bytes, largest free heap block: %u bytes", - request_size, free_heap); - return "{}"; + size_t request_size = std::min(free_heap, (size_t) 512); + while (true) { + ESP_LOGV(TAG, "Attempting to allocate %u bytes for JSON serialization", request_size); + DynamicJsonDocument json_document(request_size); + if (json_document.capacity() == 0) { + ESP_LOGE(TAG, + "Could not allocate memory for JSON document! Requested %u bytes, largest free heap block: %u bytes", + request_size, free_heap); + return "{}"; + } + JsonObject root = json_document.to(); + f(root); + if (json_document.overflowed()) { + if (request_size == free_heap) { + ESP_LOGE(TAG, "Could not allocate memory for JSON document! Overflowed largest free heap block: %u bytes", + free_heap); + return "{}"; + } + request_size = std::min(request_size * 2, free_heap); + continue; + } + json_document.shrinkToFit(); + ESP_LOGV(TAG, "Size after shrink %u bytes", json_document.capacity()); + std::string output; + serializeJson(json_document, output); + return output; } - JsonObject root = json_document.to(); - f(root); - json_document.shrinkToFit(); - ESP_LOGV(TAG, "Size after shrink %u bytes", json_document.capacity()); - std::string output; - serializeJson(json_document, output); - return output; } void parse_json(const std::string &data, const json_parse_t &f) {