feat: implement complete JSON serialization system with response classes #7
@@ -57,7 +57,23 @@ public:
|
|||||||
* @param item The serializable item to add
|
* @param item The serializable item to add
|
||||||
*/
|
*/
|
||||||
void addItem(const util::JsonSerializable& item) {
|
void addItem(const util::JsonSerializable& item) {
|
||||||
JsonArray arr = doc[collectionKey].to<JsonArray>();
|
if (!doc[collectionKey].is<JsonArray>()) {
|
||||||
|
doc[collectionKey] = JsonArray();
|
||||||
|
}
|
||||||
|
JsonArray arr = doc[collectionKey].as<JsonArray>();
|
||||||
|
JsonObject obj = arr.add<JsonObject>();
|
||||||
|
item.toJson(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a serializable item to the collection (move version)
|
||||||
|
* @param item The serializable item to add
|
||||||
|
*/
|
||||||
|
void addItem(util::JsonSerializable&& item) {
|
||||||
|
if (!doc[collectionKey].is<JsonArray>()) {
|
||||||
|
doc[collectionKey] = JsonArray();
|
||||||
|
}
|
||||||
|
JsonArray arr = doc[collectionKey].as<JsonArray>();
|
||||||
JsonObject obj = arr.add<JsonObject>();
|
JsonObject obj = arr.add<JsonObject>();
|
||||||
item.toJson(obj);
|
item.toJson(obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ public:
|
|||||||
* @param node The NodeInfo to add
|
* @param node The NodeInfo to add
|
||||||
*/
|
*/
|
||||||
void addNode(const NodeInfo& node) {
|
void addNode(const NodeInfo& node) {
|
||||||
NodeInfoSerializable serializable(const_cast<NodeInfo&>(node));
|
addItem(NodeInfoSerializable(const_cast<NodeInfo&>(node)));
|
||||||
addItem(serializable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -60,8 +60,7 @@ public:
|
|||||||
* @param endpoint The EndpointInfo to add
|
* @param endpoint The EndpointInfo to add
|
||||||
*/
|
*/
|
||||||
void addEndpoint(const EndpointInfo& endpoint) {
|
void addEndpoint(const EndpointInfo& endpoint) {
|
||||||
EndpointInfoSerializable serializable(endpoint);
|
addItem(EndpointInfoSerializable(endpoint));
|
||||||
addItem(serializable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,16 @@ namespace types {
|
|||||||
*/
|
*/
|
||||||
class TaskInfoSerializable : public util::JsonSerializable {
|
class TaskInfoSerializable : public util::JsonSerializable {
|
||||||
private:
|
private:
|
||||||
const String& taskName;
|
String taskName;
|
||||||
const JsonObject& taskData;
|
const JsonObject& taskData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TaskInfoSerializable(const String& name, const JsonObject& data)
|
TaskInfoSerializable(const String& name, const JsonObject& data)
|
||||||
: taskName(name), taskData(data) {}
|
: taskName(name), taskData(data) {}
|
||||||
|
|
||||||
|
TaskInfoSerializable(const std::string& name, const JsonObject& data)
|
||||||
|
: taskName(name.c_str()), taskData(data) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize task info to JsonObject
|
* Serialize task info to JsonObject
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void addTask(const String& taskName, const JsonObject& taskData) {
|
void addTask(const String& taskName, const JsonObject& taskData) {
|
||||||
TaskInfoSerializable serializable(taskName, taskData);
|
TaskInfoSerializable serializable(taskName, taskData);
|
||||||
JsonArray tasksArr = doc["tasks"].to<JsonArray>();
|
if (!doc["tasks"].is<JsonArray>()) {
|
||||||
|
doc["tasks"] = JsonArray();
|
||||||
|
}
|
||||||
|
JsonArray tasksArr = doc["tasks"].as<JsonArray>();
|
||||||
JsonObject taskObj = tasksArr.add<JsonObject>();
|
JsonObject taskObj = tasksArr.add<JsonObject>();
|
||||||
serializable.toJson(taskObj);
|
serializable.toJson(taskObj);
|
||||||
}
|
}
|
||||||
@@ -41,8 +44,11 @@ public:
|
|||||||
* @param taskData Task data as JsonObject
|
* @param taskData Task data as JsonObject
|
||||||
*/
|
*/
|
||||||
void addTask(const std::string& taskName, const JsonObject& taskData) {
|
void addTask(const std::string& taskName, const JsonObject& taskData) {
|
||||||
TaskInfoSerializable serializable(String(taskName.c_str()), taskData);
|
TaskInfoSerializable serializable(taskName, taskData);
|
||||||
JsonArray tasksArr = doc["tasks"].to<JsonArray>();
|
if (!doc["tasks"].is<JsonArray>()) {
|
||||||
|
doc["tasks"] = JsonArray();
|
||||||
|
}
|
||||||
|
JsonArray tasksArr = doc["tasks"].as<JsonArray>();
|
||||||
JsonObject taskObj = tasksArr.add<JsonObject>();
|
JsonObject taskObj = tasksArr.add<JsonObject>();
|
||||||
serializable.toJson(taskObj);
|
serializable.toJson(taskObj);
|
||||||
}
|
}
|
||||||
@@ -93,6 +99,9 @@ public:
|
|||||||
* @param taskStatuses Vector of pairs of task name to task data
|
* @param taskStatuses Vector of pairs of task name to task data
|
||||||
*/
|
*/
|
||||||
void buildCompleteResponse(const std::vector<std::pair<std::string, JsonObject>>& taskStatuses) {
|
void buildCompleteResponse(const std::vector<std::pair<std::string, JsonObject>>& taskStatuses) {
|
||||||
|
// Clear the document first since getAllTaskStatuses creates a root array
|
||||||
|
doc.clear();
|
||||||
|
|
||||||
// Set summary
|
// Set summary
|
||||||
size_t totalTasks = taskStatuses.size();
|
size_t totalTasks = taskStatuses.size();
|
||||||
size_t activeTasks = 0;
|
size_t activeTasks = 0;
|
||||||
@@ -103,9 +112,23 @@ public:
|
|||||||
}
|
}
|
||||||
setSummary(totalTasks, activeTasks);
|
setSummary(totalTasks, activeTasks);
|
||||||
|
|
||||||
// Add all tasks
|
// Add all tasks - extract data before clearing to avoid invalid references
|
||||||
|
JsonArray tasksArr = doc["tasks"].to<JsonArray>();
|
||||||
for (const auto& pair : taskStatuses) {
|
for (const auto& pair : taskStatuses) {
|
||||||
addTask(pair.first, pair.second);
|
// Extract data from JsonObject before it becomes invalid
|
||||||
|
String taskName = pair.first.c_str();
|
||||||
|
unsigned long interval = pair.second["interval"];
|
||||||
|
bool enabled = pair.second["enabled"];
|
||||||
|
bool running = pair.second["running"];
|
||||||
|
bool autoStart = pair.second["autoStart"];
|
||||||
|
|
||||||
|
// Create new JsonObject in our document
|
||||||
|
JsonObject taskObj = tasksArr.add<JsonObject>();
|
||||||
|
taskObj["name"] = taskName;
|
||||||
|
taskObj["interval"] = interval;
|
||||||
|
taskObj["enabled"] = enabled;
|
||||||
|
taskObj["running"] = running;
|
||||||
|
taskObj["autoStart"] = autoStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set system info
|
// Set system info
|
||||||
|
|||||||
@@ -36,10 +36,13 @@ void TaskService::registerEndpoints(ApiServer& api) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TaskService::handleStatusRequest(AsyncWebServerRequest* request) {
|
void TaskService::handleStatusRequest(AsyncWebServerRequest* request) {
|
||||||
|
TaskStatusResponse response;
|
||||||
|
|
||||||
|
// Get task statuses using a separate document to avoid reference issues
|
||||||
JsonDocument scratch;
|
JsonDocument scratch;
|
||||||
auto taskStatuses = taskManager.getAllTaskStatuses(scratch);
|
auto taskStatuses = taskManager.getAllTaskStatuses(scratch);
|
||||||
|
|
||||||
TaskStatusResponse response;
|
// Build the complete response with the task data
|
||||||
response.buildCompleteResponse(taskStatuses);
|
response.buildCompleteResponse(taskStatuses);
|
||||||
request->send(200, "application/json", response.toJsonString());
|
request->send(200, "application/json", response.toJsonString());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user