summaryrefslogtreecommitdiff
path: root/redfish-core
diff options
context:
space:
mode:
authorEd Tanous <ed@tanous.net>2024-03-06 23:04:01 +0300
committerEd Tanous <ed@tanous.net>2024-03-19 03:34:21 +0300
commitb6164cbec4dd7f5c4e6e7667b203874e11cd8b3c (patch)
tree37f79b6897b8e075be9895314912d70ed9fb910a /redfish-core
parentb2896149c39967dd9d1ee79357bdc53537cfabd7 (diff)
downloadbmcweb-b6164cbec4dd7f5c4e6e7667b203874e11cd8b3c.tar.xz
Make readJson accept object_t
Redfish supports several type systems for json. This makes parsing into proper types a challenge. Nlohmann supports 3 core data types, nlohmann::json, which supports all json types (float, int, array, object). Nlohmann::json::object_t, which is a specific typedef of std::map, and nlohmann::json::array_t, which is a specific typedef of std::map. Redfish allows reading our arrays of complex objects, similar to NtpServers: [null, {}, "string"] Which makes it a challenge to support. This commit allows parsing out objects as a nlohmann::object_t, which gives the ability to later use it in a type safe manner, without having to call get_ptr<nlohmann::json::object_t later>. Tested: Unit tests pass. Change-Id: I4134338951ce27c2f56841a45b56bc64ad1753db Signed-off-by: Ed Tanous <ed@tanous.net>
Diffstat (limited to 'redfish-core')
-rw-r--r--redfish-core/include/utils/json_utils.hpp84
1 files changed, 66 insertions, 18 deletions
diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp
index 82f1fe2b64..c8af2d15db 100644
--- a/redfish-core/include/utils/json_utils.hpp
+++ b/redfish-core/include/utils/json_utils.hpp
@@ -341,6 +341,7 @@ using UnpackVariant = std::variant<
double*,
std::string*,
nlohmann::json*,
+ nlohmann::json::object_t*,
std::vector<uint8_t>*,
std::vector<uint16_t>*,
std::vector<int16_t>*,
@@ -352,6 +353,7 @@ using UnpackVariant = std::variant<
std::vector<double>*,
std::vector<std::string>*,
std::vector<nlohmann::json>*,
+ std::vector<nlohmann::json::object_t>*,
std::optional<uint8_t>*,
std::optional<uint16_t>*,
std::optional<int16_t>*,
@@ -363,6 +365,7 @@ using UnpackVariant = std::variant<
std::optional<double>*,
std::optional<std::string>*,
std::optional<nlohmann::json>*,
+ std::optional<nlohmann::json::object_t>*,
std::optional<std::vector<uint8_t>>*,
std::optional<std::vector<uint16_t>>*,
std::optional<std::vector<int16_t>>*,
@@ -373,7 +376,8 @@ using UnpackVariant = std::variant<
//std::optional<std::vector<bool>>*,
std::optional<std::vector<double>>*,
std::optional<std::vector<std::string>>*,
- std::optional<std::vector<nlohmann::json>>*
+ std::optional<std::vector<nlohmann::json>>*,
+ std::optional<std::vector<nlohmann::json::object_t>>*
>;
// clang-format on
@@ -385,18 +389,14 @@ struct PerUnpack
};
inline bool readJsonHelper(nlohmann::json& jsonRequest, crow::Response& res,
- std::span<PerUnpack> toUnpack)
+ std::span<PerUnpack> toUnpack);
+
+inline bool readJsonHelperObject(nlohmann::json::object_t& obj,
+ crow::Response& res,
+ std::span<PerUnpack> toUnpack)
{
bool result = true;
- nlohmann::json::object_t* obj =
- jsonRequest.get_ptr<nlohmann::json::object_t*>();
- if (obj == nullptr)
- {
- BMCWEB_LOG_DEBUG("Json value is not an object");
- messages::unrecognizedRequestBody(res);
- return false;
- }
- for (auto& item : *obj)
+ for (auto& item : obj)
{
size_t unpackIndex = 0;
for (; unpackIndex < toUnpack.size(); unpackIndex++)
@@ -489,6 +489,20 @@ inline bool readJsonHelper(nlohmann::json& jsonRequest, crow::Response& res,
return result;
}
+inline bool readJsonHelper(nlohmann::json& jsonRequest, crow::Response& res,
+ std::span<PerUnpack> toUnpack)
+{
+ nlohmann::json::object_t* obj =
+ jsonRequest.get_ptr<nlohmann::json::object_t*>();
+ if (obj == nullptr)
+ {
+ BMCWEB_LOG_DEBUG("Json value is not an object");
+ messages::unrecognizedRequestBody(res);
+ return false;
+ }
+ return readJsonHelperObject(*obj, res, toUnpack);
+}
+
inline void packVariant(std::span<PerUnpack> /*toPack*/) {}
template <typename FirstType, typename... UnpackTypes>
@@ -506,16 +520,32 @@ void packVariant(std::span<PerUnpack> toPack, std::string_view key,
}
template <typename FirstType, typename... UnpackTypes>
-bool readJson(nlohmann::json& jsonRequest, crow::Response& res,
- std::string_view key, FirstType&& first, UnpackTypes&&... in)
+bool readJsonObject(nlohmann::json::object_t& jsonRequest, crow::Response& res,
+ std::string_view key, FirstType&& first,
+ UnpackTypes&&... in)
{
const std::size_t n = sizeof...(UnpackTypes) + 2;
std::array<PerUnpack, n / 2> toUnpack2;
packVariant(toUnpack2, key, first, std::forward<UnpackTypes&&>(in)...);
- return readJsonHelper(jsonRequest, res, toUnpack2);
+ return readJsonHelperObject(jsonRequest, res, toUnpack2);
+}
+
+template <typename FirstType, typename... UnpackTypes>
+bool readJson(nlohmann::json& jsonRequest, crow::Response& res,
+ std::string_view key, FirstType&& first, UnpackTypes&&... in)
+{
+ nlohmann::json::object_t* obj =
+ jsonRequest.get_ptr<nlohmann::json::object_t*>();
+ if (obj == nullptr)
+ {
+ BMCWEB_LOG_DEBUG("Json value is not an object");
+ messages::unrecognizedRequestBody(res);
+ return false;
+ }
+ return readJsonObject(*obj, res, key, first, in...);
}
-inline std::optional<nlohmann::json>
+inline std::optional<nlohmann::json::object_t>
readJsonPatchHelper(const crow::Request& req, crow::Response& res)
{
nlohmann::json jsonRequest;
@@ -545,7 +575,7 @@ inline std::optional<nlohmann::json>
return std::nullopt;
}
- return {std::move(jsonRequest)};
+ return {std::move(*object)};
}
template <typename... UnpackTypes>
@@ -557,8 +587,17 @@ bool readJsonPatch(const crow::Request& req, crow::Response& res,
{
return false;
}
+ nlohmann::json::object_t* object =
+ jsonRequest->get_ptr<nlohmann::json::object_t*>();
+ if (object == nullptr)
+ {
+ BMCWEB_LOG_DEBUG("Json value is empty");
+ messages::emptyJSON(res);
+ return false;
+ }
- return readJson(*jsonRequest, res, key, std::forward<UnpackTypes&&>(in)...);
+ return readJsonObject(*object, res, key,
+ std::forward<UnpackTypes&&>(in)...);
}
template <typename... UnpackTypes>
@@ -571,7 +610,16 @@ bool readJsonAction(const crow::Request& req, crow::Response& res,
BMCWEB_LOG_DEBUG("Json value not readable");
return false;
}
- return readJson(jsonRequest, res, key, std::forward<UnpackTypes&&>(in)...);
+ nlohmann::json::object_t* object =
+ jsonRequest.get_ptr<nlohmann::json::object_t*>();
+ if (object == nullptr)
+ {
+ BMCWEB_LOG_DEBUG("Json value is empty");
+ messages::emptyJSON(res);
+ return false;
+ }
+ return readJsonObject(*object, res, key,
+ std::forward<UnpackTypes&&>(in)...);
}
// Determines if two json objects are less, based on the presence of the