ESPHome 2025.5.0
Loading...
Searching...
No Matches
json_util.cpp
Go to the documentation of this file.
1#include "json_util.h"
2#include "esphome/core/log.h"
3
4namespace esphome {
5namespace json {
6
7static const char *const TAG = "json";
8
9static std::vector<char> global_json_build_buffer; // NOLINT
11
12std::string build_json(const json_build_t &f) {
13 // Here we are allocating up to 5kb of memory,
14 // with the heap size minus 2kb to be safe if less than 5kb
15 // as we can not have a true dynamic sized document.
16 // The excess memory is freed below with `shrinkToFit()`
17 auto free_heap = ALLOCATOR.get_max_free_block_size();
18 size_t request_size = std::min(free_heap, (size_t) 512);
19 while (true) {
20 ESP_LOGV(TAG, "Attempting to allocate %zu bytes for JSON serialization", request_size);
21 DynamicJsonDocument json_document(request_size);
22 if (json_document.capacity() == 0) {
23 ESP_LOGE(TAG,
24 "Could not allocate memory for JSON document! Requested %zu bytes, largest free heap block: %zu bytes",
25 request_size, free_heap);
26 return "{}";
27 }
28 JsonObject root = json_document.to<JsonObject>();
29 f(root);
30 if (json_document.overflowed()) {
31 if (request_size == free_heap) {
32 ESP_LOGE(TAG, "Could not allocate memory for JSON document! Overflowed largest free heap block: %zu bytes",
33 free_heap);
34 return "{}";
35 }
36 request_size = std::min(request_size * 2, free_heap);
37 continue;
38 }
39 json_document.shrinkToFit();
40 ESP_LOGV(TAG, "Size after shrink %zu bytes", json_document.capacity());
41 std::string output;
42 serializeJson(json_document, output);
43 return output;
44 }
45}
46
47bool parse_json(const std::string &data, const json_parse_t &f) {
48 // Here we are allocating 1.5 times the data size,
49 // with the heap size minus 2kb to be safe if less than that
50 // as we can not have a true dynamic sized document.
51 // The excess memory is freed below with `shrinkToFit()`
52 auto free_heap = ALLOCATOR.get_max_free_block_size();
53 size_t request_size = std::min(free_heap, (size_t) (data.size() * 1.5));
54 while (true) {
55 DynamicJsonDocument json_document(request_size);
56 if (json_document.capacity() == 0) {
57 ESP_LOGE(TAG, "Could not allocate memory for JSON document! Requested %zu bytes, free heap: %zu", request_size,
58 free_heap);
59 return false;
60 }
61 DeserializationError err = deserializeJson(json_document, data);
62 json_document.shrinkToFit();
63
64 JsonObject root = json_document.as<JsonObject>();
65
66 if (err == DeserializationError::Ok) {
67 return f(root);
68 } else if (err == DeserializationError::NoMemory) {
69 if (request_size * 2 >= free_heap) {
70 ESP_LOGE(TAG, "Can not allocate more memory for deserialization. Consider making source string smaller");
71 return false;
72 }
73 ESP_LOGV(TAG, "Increasing memory allocation.");
74 request_size *= 2;
75 continue;
76 } else {
77 ESP_LOGE(TAG, "JSON parse error: %s", err.c_str());
78 return false;
79 }
80 };
81 return false;
82}
83
84} // namespace json
85} // namespace esphome
An STL allocator that uses SPI or internal RAM.
Definition helpers.h:683
std::function< void(JsonObject)> json_build_t
Callback function typedef for building JsonObjects.
Definition json_util.h:20
bool parse_json(const std::string &data, const json_parse_t &f)
Parse a JSON string and run the provided json parse function if it's valid.
Definition json_util.cpp:47
std::string build_json(const json_build_t &f)
Build a JSON string with the provided json build function.
Definition json_util.cpp:12
std::function< bool(JsonObject)> json_parse_t
Callback function typedef for parsing JsonObjects.
Definition json_util.h:17
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7