diff options
author | Ed Tanous <ed@tanous.net> | 2024-03-06 23:04:01 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2024-03-19 03:34:21 +0300 |
commit | b6164cbec4dd7f5c4e6e7667b203874e11cd8b3c (patch) | |
tree | 37f79b6897b8e075be9895314912d70ed9fb910a /redfish-core/include/utils | |
parent | b2896149c39967dd9d1ee79357bdc53537cfabd7 (diff) | |
download | bmcweb-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/include/utils')
-rw-r--r-- | redfish-core/include/utils/json_utils.hpp | 84 |
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 |