#ifndef JSONUTIL_H #define JSONUTIL_H #include #include #include #include #include "util/xpack/json.h" #include #include #include namespace Util { class JsonUtil { private: public: template static std::string encode(T t) { return xpack::json::encode(t); } template static T decode(std::string jsonStr) { T t; xpack::json::decode(jsonStr, t); return t; } static std::string jsonToString(const Poco::JSON::Object::Ptr& jsonObject) { std::ostringstream oss; Poco::JSON::Stringifier::stringify(jsonObject, oss); return oss.str(); } static Poco::JSON::Object::Ptr stringToJson(const std::string& jsonString) { Poco::JSON::Parser parser; Poco::Dynamic::Var result = parser.parse(jsonString); return result.extract(); } static Poco::JSON::Array::Ptr stringToJsonArray(const std::string& jsonArrayString) { Poco::JSON::Parser parser; Poco::Dynamic::Var result = parser.parse(jsonArrayString); return result.extract(); } static Poco::Dynamic::Var getNestedValue(Poco::JSON::Object::Ptr json, const std::string& path) { if (path.empty()) return json; std::regex arrayRegex(R"((\w+)((?:\[\d+\])+))"); std::istringstream pathStream(path); std::string segment; Poco::Dynamic::Var currentVar = json; while (std::getline(pathStream, segment, '.')) { std::smatch match; if (std::regex_match(segment, match, arrayRegex)) { std::string arrayKey = match[1]; std::string indicesStr = match[2]; std::vector indices; std::regex indexRegex(R"(\[(\d+)\])"); std::sregex_iterator it(indicesStr.begin(), indicesStr.end(), indexRegex); std::sregex_iterator end; while (it != end) { indices.push_back(static_cast(std::stoi((*it)[1]))); ++it; } Poco::JSON::Object::Ptr obj = currentVar.extract(); if (!obj->has(arrayKey)) { throw std::runtime_error("getNestedValue Key not found: " + arrayKey); } Poco::JSON::Array::Ptr array = obj->getArray(arrayKey); if (!array) { throw std::runtime_error("getNestedValue Expected an array at key: " + arrayKey); } for (std::size_t i = 0; i < indices.size(); i++) { std::size_t index = indices[i]; if (index >= array->size()) { throw std::out_of_range("getNestedValue Array index out of bounds: " + std::to_string(index)); } currentVar = array->get(index); if (i < indices.size() - 1) { array = currentVar.extract(); if (!array) { throw std::runtime_error("getNestedValue Expected an array at index: " + std::to_string(index)); } } } } else { Poco::JSON::Object::Ptr obj = currentVar.extract(); if (!obj->has(segment)) { throw std::runtime_error("getNestedValue Key not found: " + segment); } currentVar = obj->get(segment); } } return currentVar; } static Poco::JSON::Object::Ptr getNestedValue(Poco::JSON::Object::Ptr json, const std::vector& paths) { Poco::JSON::Object::Ptr results = new Poco::JSON::Object(); for (const auto& path : paths) { results->set(path, getNestedValue(json, path)); } return results; } static void setNestedValue(Poco::JSON::Object::Ptr jsonObject, const std::string& path, const Poco::Dynamic::Var& value) { if (!jsonObject) { throw std::invalid_argument("setNestedValue JSON object is null."); } std::regex arrayRegex(R"((\w+)((?:\[\d+\])+))"); std::istringstream pathStream(path); std::string segment; Poco::JSON::Object::Ptr currentObject = jsonObject; while (std::getline(pathStream, segment, '.')) { std::smatch match; if (std::regex_match(segment, match, arrayRegex)) { std::string arrayKey = match[1]; std::string indicesStr = match[2]; std::vector indices; std::regex indexRegex(R"(\[(\d+)\])"); std::sregex_iterator it(indicesStr.begin(), indicesStr.end(), indexRegex); std::sregex_iterator end; while (it != end) { indices.push_back(static_cast(std::stoi((*it)[1]))); ++it; } Poco::JSON::Array::Ptr array; if (!currentObject->has(arrayKey)) { array = new Poco::JSON::Array(); currentObject->set(arrayKey, array); } else { array = currentObject->getArray(arrayKey); if (!array) { throw std::runtime_error("setNestedValue Expected an array at key: " + arrayKey); } } for (std::size_t i = 0; i < indices.size() - 1; i++) { while (array->size() <= indices[i]) { Poco::JSON::Array::Ptr nestedArray = new Poco::JSON::Array(); array->add(nestedArray); } Poco::JSON::Array::Ptr nextArray = array->getArray(indices[i]); if (!nextArray) { throw std::runtime_error("setNestedValue Expected an array at index: " + std::to_string(indices[i])); } array = nextArray; } std::size_t lastIndex = indices.back(); while (array->size() <= lastIndex) { Poco::JSON::Object::Ptr nestedObject = new Poco::JSON::Object(); array->add(nestedObject); } if (pathStream.peek() == EOF) { array->set(lastIndex, value); return; } currentObject = array->getObject(lastIndex); if (!currentObject) { throw std::runtime_error("setNestedValue Expected an object at index: " + std::to_string(lastIndex)); } } else { if (pathStream.peek() == EOF) { currentObject->set(segment, value); return; } if (!currentObject->has(segment)) { Poco::JSON::Object::Ptr nestedObject = new Poco::JSON::Object(); currentObject->set(segment, nestedObject); } currentObject = currentObject->getObject(segment); if (!currentObject) { throw std::runtime_error("setNestedValue Expected an object at key: " + segment); } } } } static void setNestedValue(Poco::JSON::Object::Ptr jsonObject, const std::map& pathValues) { for (const auto& kv : pathValues) { setNestedValue(jsonObject, kv.first, kv.second); } } }; } #endif