177dd8813SKowalski, Kamil /* 277dd8813SKowalski, Kamil // Copyright (c) 2018 Intel Corporation 377dd8813SKowalski, Kamil // 477dd8813SKowalski, Kamil // Licensed under the Apache License, Version 2.0 (the "License"); 577dd8813SKowalski, Kamil // you may not use this file except in compliance with the License. 677dd8813SKowalski, Kamil // You may obtain a copy of the License at 777dd8813SKowalski, Kamil // 877dd8813SKowalski, Kamil // http://www.apache.org/licenses/LICENSE-2.0 977dd8813SKowalski, Kamil // 1077dd8813SKowalski, Kamil // Unless required by applicable law or agreed to in writing, software 1177dd8813SKowalski, Kamil // distributed under the License is distributed on an "AS IS" BASIS, 1277dd8813SKowalski, Kamil // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1377dd8813SKowalski, Kamil // See the License for the specific language governing permissions and 1477dd8813SKowalski, Kamil // limitations under the License. 1577dd8813SKowalski, Kamil */ 1677dd8813SKowalski, Kamil #pragma once 179712f8acSEd Tanous 18c94ad49bSEd Tanous #include <http_request.h> 19c94ad49bSEd Tanous #include <http_response.h> 2077dd8813SKowalski, Kamil 219712f8acSEd Tanous #include <error_messages.hpp> 221abe55efSEd Tanous #include <nlohmann/json.hpp> 230627a2c7SEd Tanous 24*1214b7e7SGunnar Mills #include <bitset> 25*1214b7e7SGunnar Mills 261abe55efSEd Tanous namespace redfish 271abe55efSEd Tanous { 281abe55efSEd Tanous 291abe55efSEd Tanous namespace json_util 301abe55efSEd Tanous { 3177dd8813SKowalski, Kamil 3277dd8813SKowalski, Kamil /** 3377dd8813SKowalski, Kamil * @brief Processes request to extract JSON from its body. If it fails, adds 3477dd8813SKowalski, Kamil * MalformedJSON message to response and ends it. 3577dd8813SKowalski, Kamil * 3677dd8813SKowalski, Kamil * @param[io] res Response object 3777dd8813SKowalski, Kamil * @param[in] req Request object 3877dd8813SKowalski, Kamil * @param[out] reqJson JSON object extracted from request's body 3977dd8813SKowalski, Kamil * 4077dd8813SKowalski, Kamil * @return true if JSON is valid, false when JSON is invalid and response has 4177dd8813SKowalski, Kamil * been filled with message and ended. 4277dd8813SKowalski, Kamil */ 4355c7b7a2SEd Tanous bool processJsonFromRequest(crow::Response& res, const crow::Request& req, 4477dd8813SKowalski, Kamil nlohmann::json& reqJson); 459712f8acSEd Tanous namespace details 469712f8acSEd Tanous { 47771cfa0fSJason M. Bills 48*1214b7e7SGunnar Mills template <typename Type> 49*1214b7e7SGunnar Mills struct is_optional : std::false_type 50*1214b7e7SGunnar Mills {}; 519712f8acSEd Tanous 52771cfa0fSJason M. Bills template <typename Type> 53a24526dcSEd Tanous struct is_optional<std::optional<Type>> : std::true_type 54*1214b7e7SGunnar Mills {}; 559712f8acSEd Tanous 56771cfa0fSJason M. Bills template <typename Type> 57771cfa0fSJason M. Bills constexpr bool is_optional_v = is_optional<Type>::value; 58771cfa0fSJason M. Bills 59*1214b7e7SGunnar Mills template <typename Type> 60*1214b7e7SGunnar Mills struct is_vector : std::false_type 61*1214b7e7SGunnar Mills {}; 62b1556427SEd Tanous 63*1214b7e7SGunnar Mills template <typename Type> 64*1214b7e7SGunnar Mills struct is_vector<std::vector<Type>> : std::true_type 65*1214b7e7SGunnar Mills {}; 66b1556427SEd Tanous 67*1214b7e7SGunnar Mills template <typename Type> 68*1214b7e7SGunnar Mills constexpr bool is_vector_v = is_vector<Type>::value; 69b1556427SEd Tanous 70*1214b7e7SGunnar Mills template <typename Type> 71*1214b7e7SGunnar Mills struct is_std_array : std::false_type 72*1214b7e7SGunnar Mills {}; 73318226c2SJames Feist 74318226c2SJames Feist template <typename Type, std::size_t size> 75318226c2SJames Feist struct is_std_array<std::array<Type, size>> : std::true_type 76*1214b7e7SGunnar Mills {}; 77318226c2SJames Feist 78318226c2SJames Feist template <typename Type> 79318226c2SJames Feist constexpr bool is_std_array_v = is_std_array<Type>::value; 80318226c2SJames Feist 81471a5eb8SAppaRao Puli enum class UnpackErrorCode 82471a5eb8SAppaRao Puli { 83471a5eb8SAppaRao Puli success, 84471a5eb8SAppaRao Puli invalidType, 85471a5eb8SAppaRao Puli outOfRange 86471a5eb8SAppaRao Puli }; 87471a5eb8SAppaRao Puli 88a6acbb31SJames Feist template <typename ToType, typename FromType> 89471a5eb8SAppaRao Puli bool checkRange(const FromType& from, nlohmann::json& jsonValue, 90471a5eb8SAppaRao Puli const std::string& key) 91a6acbb31SJames Feist { 92ee344e0fSEd Tanous if (from > std::numeric_limits<ToType>::max()) 93a6acbb31SJames Feist { 94a6acbb31SJames Feist BMCWEB_LOG_DEBUG << "Value for key " << key 95a6acbb31SJames Feist << " was greater than max: " << __PRETTY_FUNCTION__; 96a6acbb31SJames Feist return false; 97a6acbb31SJames Feist } 98ee344e0fSEd Tanous if (from < std::numeric_limits<ToType>::lowest()) 99a6acbb31SJames Feist { 100a6acbb31SJames Feist BMCWEB_LOG_DEBUG << "Value for key " << key 101a6acbb31SJames Feist << " was less than min: " << __PRETTY_FUNCTION__; 102a6acbb31SJames Feist return false; 103a6acbb31SJames Feist } 104a6acbb31SJames Feist if constexpr (std::is_floating_point_v<ToType>) 105a6acbb31SJames Feist { 106ee344e0fSEd Tanous if (std::isnan(from)) 107a6acbb31SJames Feist { 108a6acbb31SJames Feist BMCWEB_LOG_DEBUG << "Value for key " << key << " was NAN"; 109a6acbb31SJames Feist return false; 110a6acbb31SJames Feist } 111a6acbb31SJames Feist } 112a6acbb31SJames Feist 113a6acbb31SJames Feist return true; 114a6acbb31SJames Feist } 115a6acbb31SJames Feist 116771cfa0fSJason M. Bills template <typename Type> 117471a5eb8SAppaRao Puli UnpackErrorCode unpackValueWithErrorCode(nlohmann::json& jsonValue, 118471a5eb8SAppaRao Puli const std::string& key, Type& value) 119771cfa0fSJason M. Bills { 120471a5eb8SAppaRao Puli UnpackErrorCode ret = UnpackErrorCode::success; 12141352c24SSantosh Puranik 122a6acbb31SJames Feist if constexpr (std::is_floating_point_v<Type>) 123771cfa0fSJason M. Bills { 124a6acbb31SJames Feist double helper = 0; 125a6acbb31SJames Feist double* jsonPtr = jsonValue.get_ptr<double*>(); 126771cfa0fSJason M. Bills 127771cfa0fSJason M. Bills if (jsonPtr == nullptr) 128771cfa0fSJason M. Bills { 129a6acbb31SJames Feist int64_t* intPtr = jsonValue.get_ptr<int64_t*>(); 130a6acbb31SJames Feist if (intPtr != nullptr) 131771cfa0fSJason M. Bills { 132a6acbb31SJames Feist helper = static_cast<double>(*intPtr); 133a6acbb31SJames Feist jsonPtr = &helper; 134771cfa0fSJason M. Bills } 135a6acbb31SJames Feist } 1365eb2bef2SAppaRao Puli if (jsonPtr == nullptr) 1375eb2bef2SAppaRao Puli { 138471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 1395eb2bef2SAppaRao Puli } 140471a5eb8SAppaRao Puli if (!checkRange<Type>(*jsonPtr, jsonValue, key)) 141771cfa0fSJason M. Bills { 142471a5eb8SAppaRao Puli return UnpackErrorCode::outOfRange; 143771cfa0fSJason M. Bills } 144771cfa0fSJason M. Bills value = static_cast<Type>(*jsonPtr); 145771cfa0fSJason M. Bills } 146a6acbb31SJames Feist 147a6acbb31SJames Feist else if constexpr (std::is_signed_v<Type>) 148a6acbb31SJames Feist { 149a6acbb31SJames Feist int64_t* jsonPtr = jsonValue.get_ptr<int64_t*>(); 150271584abSEd Tanous if (jsonPtr == nullptr) 151271584abSEd Tanous { 152471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 153271584abSEd Tanous } 154471a5eb8SAppaRao Puli if (!checkRange<Type>(*jsonPtr, jsonValue, key)) 155a6acbb31SJames Feist { 156471a5eb8SAppaRao Puli return UnpackErrorCode::outOfRange; 157a6acbb31SJames Feist } 158a6acbb31SJames Feist value = static_cast<Type>(*jsonPtr); 159a6acbb31SJames Feist } 160a6acbb31SJames Feist 1618102ddbaSAppaRao Puli else if constexpr ((std::is_unsigned_v<Type>)&&( 1628102ddbaSAppaRao Puli !std::is_same_v<bool, Type>)) 163a6acbb31SJames Feist { 164a6acbb31SJames Feist uint64_t* jsonPtr = jsonValue.get_ptr<uint64_t*>(); 165271584abSEd Tanous if (jsonPtr == nullptr) 166271584abSEd Tanous { 167471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 168271584abSEd Tanous } 169471a5eb8SAppaRao Puli if (!checkRange<Type>(*jsonPtr, jsonValue, key)) 170a6acbb31SJames Feist { 171471a5eb8SAppaRao Puli return UnpackErrorCode::outOfRange; 172a6acbb31SJames Feist } 173a6acbb31SJames Feist value = static_cast<Type>(*jsonPtr); 174a6acbb31SJames Feist } 175a6acbb31SJames Feist 1760627a2c7SEd Tanous else if constexpr (std::is_same_v<nlohmann::json, Type>) 1770627a2c7SEd Tanous { 1780627a2c7SEd Tanous // Must be a complex type. Simple types (int string etc) should be 1790627a2c7SEd Tanous // unpacked directly 1808ebc91f6SEd Tanous if (!jsonValue.is_object() && !jsonValue.is_array() && 1818ebc91f6SEd Tanous !jsonValue.is_null()) 1820627a2c7SEd Tanous { 183471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 1840627a2c7SEd Tanous } 1850627a2c7SEd Tanous 1860627a2c7SEd Tanous value = std::move(jsonValue); 1870627a2c7SEd Tanous } 188471a5eb8SAppaRao Puli else 189471a5eb8SAppaRao Puli { 190471a5eb8SAppaRao Puli using JsonType = std::add_const_t<std::add_pointer_t<Type>>; 191471a5eb8SAppaRao Puli JsonType jsonPtr = jsonValue.get_ptr<JsonType>(); 192471a5eb8SAppaRao Puli if (jsonPtr == nullptr) 193471a5eb8SAppaRao Puli { 194471a5eb8SAppaRao Puli BMCWEB_LOG_DEBUG 195471a5eb8SAppaRao Puli << "Value for key " << key 196471a5eb8SAppaRao Puli << " was incorrect type: " << jsonValue.type_name(); 197471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 198471a5eb8SAppaRao Puli } 199471a5eb8SAppaRao Puli value = std::move(*jsonPtr); 200471a5eb8SAppaRao Puli } 201471a5eb8SAppaRao Puli return ret; 202471a5eb8SAppaRao Puli } 203471a5eb8SAppaRao Puli 204471a5eb8SAppaRao Puli template <typename Type> 205471a5eb8SAppaRao Puli bool unpackValue(nlohmann::json& jsonValue, const std::string& key, 206471a5eb8SAppaRao Puli crow::Response& res, Type& value) 207471a5eb8SAppaRao Puli { 208471a5eb8SAppaRao Puli bool ret = true; 209471a5eb8SAppaRao Puli 210471a5eb8SAppaRao Puli if constexpr (is_optional_v<Type>) 211471a5eb8SAppaRao Puli { 212471a5eb8SAppaRao Puli value.emplace(); 213471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(jsonValue, key, res, 214471a5eb8SAppaRao Puli *value) && 215471a5eb8SAppaRao Puli ret; 216471a5eb8SAppaRao Puli } 217318226c2SJames Feist else if constexpr (is_std_array_v<Type>) 218318226c2SJames Feist { 219318226c2SJames Feist if (!jsonValue.is_array()) 220318226c2SJames Feist { 221318226c2SJames Feist messages::propertyValueTypeError(res, res.jsonValue.dump(), key); 22241352c24SSantosh Puranik return false; 223318226c2SJames Feist } 224318226c2SJames Feist if (jsonValue.size() != value.size()) 225318226c2SJames Feist { 226318226c2SJames Feist messages::propertyValueTypeError(res, res.jsonValue.dump(), key); 22741352c24SSantosh Puranik return false; 228318226c2SJames Feist } 229318226c2SJames Feist size_t index = 0; 230318226c2SJames Feist for (const auto& val : jsonValue.items()) 231318226c2SJames Feist { 23241352c24SSantosh Puranik ret = unpackValue<typename Type::value_type>(val.value(), key, res, 23341352c24SSantosh Puranik value[index++]) && 23441352c24SSantosh Puranik ret; 235318226c2SJames Feist } 236318226c2SJames Feist } 237b1556427SEd Tanous else if constexpr (is_vector_v<Type>) 238b1556427SEd Tanous { 239b1556427SEd Tanous if (!jsonValue.is_array()) 240b1556427SEd Tanous { 241b1556427SEd Tanous messages::propertyValueTypeError(res, res.jsonValue.dump(), key); 24241352c24SSantosh Puranik return false; 243b1556427SEd Tanous } 244b1556427SEd Tanous 245b1556427SEd Tanous for (const auto& val : jsonValue.items()) 246b1556427SEd Tanous { 247b1556427SEd Tanous value.emplace_back(); 24841352c24SSantosh Puranik ret = unpackValue<typename Type::value_type>(val.value(), key, res, 24941352c24SSantosh Puranik value.back()) && 25041352c24SSantosh Puranik ret; 251b1556427SEd Tanous } 252b1556427SEd Tanous } 253771cfa0fSJason M. Bills else 254771cfa0fSJason M. Bills { 255471a5eb8SAppaRao Puli UnpackErrorCode ec = unpackValueWithErrorCode(jsonValue, key, value); 256471a5eb8SAppaRao Puli if (ec != UnpackErrorCode::success) 257771cfa0fSJason M. Bills { 258471a5eb8SAppaRao Puli if (ec == UnpackErrorCode::invalidType) 259471a5eb8SAppaRao Puli { 260771cfa0fSJason M. Bills messages::propertyValueTypeError(res, jsonValue.dump(), key); 261471a5eb8SAppaRao Puli } 262471a5eb8SAppaRao Puli else if (ec == UnpackErrorCode::outOfRange) 263471a5eb8SAppaRao Puli { 264471a5eb8SAppaRao Puli messages::propertyValueNotInList(res, jsonValue.dump(), key); 265471a5eb8SAppaRao Puli } 26641352c24SSantosh Puranik return false; 267771cfa0fSJason M. Bills } 268771cfa0fSJason M. Bills } 269471a5eb8SAppaRao Puli 270471a5eb8SAppaRao Puli return ret; 271471a5eb8SAppaRao Puli } 272471a5eb8SAppaRao Puli 273471a5eb8SAppaRao Puli template <typename Type> 274471a5eb8SAppaRao Puli bool unpackValue(nlohmann::json& jsonValue, const std::string& key, Type& value) 275471a5eb8SAppaRao Puli { 276471a5eb8SAppaRao Puli bool ret = true; 277471a5eb8SAppaRao Puli if constexpr (is_optional_v<Type>) 278471a5eb8SAppaRao Puli { 279471a5eb8SAppaRao Puli value.emplace(); 280471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(jsonValue, key, *value) && 281471a5eb8SAppaRao Puli ret; 282471a5eb8SAppaRao Puli } 283471a5eb8SAppaRao Puli else if constexpr (is_std_array_v<Type>) 284471a5eb8SAppaRao Puli { 285471a5eb8SAppaRao Puli if (!jsonValue.is_array()) 286471a5eb8SAppaRao Puli { 287471a5eb8SAppaRao Puli return false; 288471a5eb8SAppaRao Puli } 289471a5eb8SAppaRao Puli if (jsonValue.size() != value.size()) 290471a5eb8SAppaRao Puli { 291471a5eb8SAppaRao Puli return false; 292471a5eb8SAppaRao Puli } 293471a5eb8SAppaRao Puli size_t index = 0; 294471a5eb8SAppaRao Puli for (const auto& val : jsonValue.items()) 295471a5eb8SAppaRao Puli { 296471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(val.value(), key, 297471a5eb8SAppaRao Puli value[index++]) && 298471a5eb8SAppaRao Puli ret; 299471a5eb8SAppaRao Puli } 300471a5eb8SAppaRao Puli } 301471a5eb8SAppaRao Puli else if constexpr (is_vector_v<Type>) 302471a5eb8SAppaRao Puli { 303471a5eb8SAppaRao Puli if (!jsonValue.is_array()) 304471a5eb8SAppaRao Puli { 305471a5eb8SAppaRao Puli return false; 306471a5eb8SAppaRao Puli } 307471a5eb8SAppaRao Puli 308471a5eb8SAppaRao Puli for (const auto& val : jsonValue.items()) 309471a5eb8SAppaRao Puli { 310471a5eb8SAppaRao Puli value.emplace_back(); 311471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(val.value(), key, 312471a5eb8SAppaRao Puli value.back()) && 313471a5eb8SAppaRao Puli ret; 314471a5eb8SAppaRao Puli } 315471a5eb8SAppaRao Puli } 316471a5eb8SAppaRao Puli else 317471a5eb8SAppaRao Puli { 318471a5eb8SAppaRao Puli UnpackErrorCode ec = unpackValueWithErrorCode(jsonValue, key, value); 319471a5eb8SAppaRao Puli if (ec != UnpackErrorCode::success) 320471a5eb8SAppaRao Puli { 321471a5eb8SAppaRao Puli return false; 322471a5eb8SAppaRao Puli } 323471a5eb8SAppaRao Puli } 324471a5eb8SAppaRao Puli 32541352c24SSantosh Puranik return ret; 326771cfa0fSJason M. Bills } 327771cfa0fSJason M. Bills 3289712f8acSEd Tanous template <size_t Count, size_t Index> 32941352c24SSantosh Puranik bool readJsonValues(const std::string& key, nlohmann::json& jsonValue, 3309712f8acSEd Tanous crow::Response& res, std::bitset<Count>& handled) 3319712f8acSEd Tanous { 3329712f8acSEd Tanous BMCWEB_LOG_DEBUG << "Unable to find variable for key" << key; 333a08b46ccSJason M. Bills messages::propertyUnknown(res, key); 33441352c24SSantosh Puranik return false; 3359712f8acSEd Tanous } 3369712f8acSEd Tanous 3379712f8acSEd Tanous template <size_t Count, size_t Index, typename ValueType, 3389712f8acSEd Tanous typename... UnpackTypes> 33941352c24SSantosh Puranik bool readJsonValues(const std::string& key, nlohmann::json& jsonValue, 3409712f8acSEd Tanous crow::Response& res, std::bitset<Count>& handled, 3419712f8acSEd Tanous const char* keyToCheck, ValueType& valueToFill, 3429712f8acSEd Tanous UnpackTypes&... in) 3439712f8acSEd Tanous { 34441352c24SSantosh Puranik bool ret = true; 3459712f8acSEd Tanous if (key != keyToCheck) 3469712f8acSEd Tanous { 34741352c24SSantosh Puranik ret = readJsonValues<Count, Index + 1>(key, jsonValue, res, handled, 34841352c24SSantosh Puranik in...) && 34941352c24SSantosh Puranik ret; 35041352c24SSantosh Puranik return ret; 3519712f8acSEd Tanous } 3529712f8acSEd Tanous 3539712f8acSEd Tanous handled.set(Index); 3549712f8acSEd Tanous 35541352c24SSantosh Puranik return unpackValue<ValueType>(jsonValue, key, res, valueToFill) && ret; 3569712f8acSEd Tanous } 3579712f8acSEd Tanous 3589712f8acSEd Tanous template <size_t Index = 0, size_t Count> 35941352c24SSantosh Puranik bool handleMissing(std::bitset<Count>& handled, crow::Response& res) 3609712f8acSEd Tanous { 36141352c24SSantosh Puranik return true; 3629712f8acSEd Tanous } 3639712f8acSEd Tanous 3649712f8acSEd Tanous template <size_t Index = 0, size_t Count, typename ValueType, 3659712f8acSEd Tanous typename... UnpackTypes> 36641352c24SSantosh Puranik bool handleMissing(std::bitset<Count>& handled, crow::Response& res, 3679712f8acSEd Tanous const char* key, ValueType& unused, UnpackTypes&... in) 3689712f8acSEd Tanous { 36941352c24SSantosh Puranik bool ret = true; 370771cfa0fSJason M. Bills if (!handled.test(Index) && !is_optional_v<ValueType>) 3719712f8acSEd Tanous { 37241352c24SSantosh Puranik ret = false; 373a08b46ccSJason M. Bills messages::propertyMissing(res, key); 3749712f8acSEd Tanous } 37541352c24SSantosh Puranik return details::handleMissing<Index + 1, Count>(handled, res, in...) && ret; 3769712f8acSEd Tanous } 3779712f8acSEd Tanous } // namespace details 3789712f8acSEd Tanous 3799712f8acSEd Tanous template <typename... UnpackTypes> 3800627a2c7SEd Tanous bool readJson(nlohmann::json& jsonRequest, crow::Response& res, const char* key, 3819712f8acSEd Tanous UnpackTypes&... in) 3829712f8acSEd Tanous { 38341352c24SSantosh Puranik bool result = true; 3849712f8acSEd Tanous if (!jsonRequest.is_object()) 3859712f8acSEd Tanous { 3869712f8acSEd Tanous BMCWEB_LOG_DEBUG << "Json value is not an object"; 387f12894f8SJason M. Bills messages::unrecognizedRequestBody(res); 3889712f8acSEd Tanous return false; 3899712f8acSEd Tanous } 3909712f8acSEd Tanous 3919712f8acSEd Tanous if (jsonRequest.empty()) 3929712f8acSEd Tanous { 3939712f8acSEd Tanous BMCWEB_LOG_DEBUG << "Json value is empty"; 394f12894f8SJason M. Bills messages::emptyJSON(res); 3959712f8acSEd Tanous return false; 3969712f8acSEd Tanous } 3979712f8acSEd Tanous 3989712f8acSEd Tanous std::bitset<(sizeof...(in) + 1) / 2> handled(0); 3999712f8acSEd Tanous for (const auto& item : jsonRequest.items()) 4009712f8acSEd Tanous { 40141352c24SSantosh Puranik result = 4029712f8acSEd Tanous details::readJsonValues<(sizeof...(in) + 1) / 2, 0, UnpackTypes...>( 40341352c24SSantosh Puranik item.key(), item.value(), res, handled, key, in...) && 40441352c24SSantosh Puranik result; 4059712f8acSEd Tanous } 4069712f8acSEd Tanous 40741352c24SSantosh Puranik BMCWEB_LOG_DEBUG << "JSON result is: " << result; 4089712f8acSEd Tanous 40941352c24SSantosh Puranik return details::handleMissing(handled, res, key, in...) && result; 4109712f8acSEd Tanous } 41177dd8813SKowalski, Kamil 4120627a2c7SEd Tanous template <typename... UnpackTypes> 4130627a2c7SEd Tanous bool readJson(const crow::Request& req, crow::Response& res, const char* key, 4140627a2c7SEd Tanous UnpackTypes&... in) 4150627a2c7SEd Tanous { 4160627a2c7SEd Tanous nlohmann::json jsonRequest; 4170627a2c7SEd Tanous if (!json_util::processJsonFromRequest(res, req, jsonRequest)) 4180627a2c7SEd Tanous { 4190627a2c7SEd Tanous BMCWEB_LOG_DEBUG << "Json value not readable"; 4200627a2c7SEd Tanous return false; 4210627a2c7SEd Tanous } 4220627a2c7SEd Tanous return readJson(jsonRequest, res, key, in...); 4230627a2c7SEd Tanous } 4240627a2c7SEd Tanous 425471a5eb8SAppaRao Puli template <typename Type> 426471a5eb8SAppaRao Puli bool getValueFromJsonObject(nlohmann::json& jsonData, const std::string& key, 427471a5eb8SAppaRao Puli Type& value) 428471a5eb8SAppaRao Puli { 429471a5eb8SAppaRao Puli nlohmann::json jsonValue = jsonData[key]; 430471a5eb8SAppaRao Puli if (jsonValue.is_null()) 431471a5eb8SAppaRao Puli { 432471a5eb8SAppaRao Puli BMCWEB_LOG_DEBUG << "Key " << key << " not exist"; 433471a5eb8SAppaRao Puli return false; 434471a5eb8SAppaRao Puli } 435471a5eb8SAppaRao Puli 436471a5eb8SAppaRao Puli return details::unpackValue(jsonValue, key, value); 437471a5eb8SAppaRao Puli } 438471a5eb8SAppaRao Puli 43977dd8813SKowalski, Kamil } // namespace json_util 44077dd8813SKowalski, Kamil } // namespace redfish 441