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 189712f8acSEd Tanous #include <error_messages.hpp> 19*04e438cbSEd Tanous #include <http_request.hpp> 20*04e438cbSEd Tanous #include <http_response.hpp> 211abe55efSEd Tanous #include <nlohmann/json.hpp> 220627a2c7SEd Tanous 231214b7e7SGunnar Mills #include <bitset> 241214b7e7SGunnar Mills 251abe55efSEd Tanous namespace redfish 261abe55efSEd Tanous { 271abe55efSEd Tanous 281abe55efSEd Tanous namespace json_util 291abe55efSEd Tanous { 3077dd8813SKowalski, Kamil 3177dd8813SKowalski, Kamil /** 3277dd8813SKowalski, Kamil * @brief Processes request to extract JSON from its body. If it fails, adds 3377dd8813SKowalski, Kamil * MalformedJSON message to response and ends it. 3477dd8813SKowalski, Kamil * 3577dd8813SKowalski, Kamil * @param[io] res Response object 3677dd8813SKowalski, Kamil * @param[in] req Request object 3777dd8813SKowalski, Kamil * @param[out] reqJson JSON object extracted from request's body 3877dd8813SKowalski, Kamil * 3977dd8813SKowalski, Kamil * @return true if JSON is valid, false when JSON is invalid and response has 4077dd8813SKowalski, Kamil * been filled with message and ended. 4177dd8813SKowalski, Kamil */ 4255c7b7a2SEd Tanous bool processJsonFromRequest(crow::Response& res, const crow::Request& req, 4377dd8813SKowalski, Kamil nlohmann::json& reqJson); 449712f8acSEd Tanous namespace details 459712f8acSEd Tanous { 46771cfa0fSJason M. Bills 471214b7e7SGunnar Mills template <typename Type> 482c70f800SEd Tanous struct IsOptional : std::false_type 491214b7e7SGunnar Mills {}; 509712f8acSEd Tanous 51771cfa0fSJason M. Bills template <typename Type> 522c70f800SEd Tanous struct IsOptional<std::optional<Type>> : std::true_type 531214b7e7SGunnar Mills {}; 549712f8acSEd Tanous 55771cfa0fSJason M. Bills template <typename Type> 562c70f800SEd Tanous struct IsVector : std::false_type 571214b7e7SGunnar Mills {}; 58b1556427SEd Tanous 591214b7e7SGunnar Mills template <typename Type> 602c70f800SEd Tanous struct IsVector<std::vector<Type>> : std::true_type 611214b7e7SGunnar Mills {}; 62b1556427SEd Tanous 631214b7e7SGunnar Mills template <typename Type> 642c70f800SEd Tanous struct IsStdArray : std::false_type 651214b7e7SGunnar Mills {}; 66318226c2SJames Feist 67318226c2SJames Feist template <typename Type, std::size_t size> 682c70f800SEd Tanous struct IsStdArray<std::array<Type, size>> : std::true_type 691214b7e7SGunnar Mills {}; 70318226c2SJames Feist 71471a5eb8SAppaRao Puli enum class UnpackErrorCode 72471a5eb8SAppaRao Puli { 73471a5eb8SAppaRao Puli success, 74471a5eb8SAppaRao Puli invalidType, 75471a5eb8SAppaRao Puli outOfRange 76471a5eb8SAppaRao Puli }; 77471a5eb8SAppaRao Puli 78a6acbb31SJames Feist template <typename ToType, typename FromType> 79cb13a392SEd Tanous bool checkRange(const FromType& from, const std::string& key) 80a6acbb31SJames Feist { 81ee344e0fSEd Tanous if (from > std::numeric_limits<ToType>::max()) 82a6acbb31SJames Feist { 83a6acbb31SJames Feist BMCWEB_LOG_DEBUG << "Value for key " << key 84a6acbb31SJames Feist << " was greater than max: " << __PRETTY_FUNCTION__; 85a6acbb31SJames Feist return false; 86a6acbb31SJames Feist } 87ee344e0fSEd Tanous if (from < std::numeric_limits<ToType>::lowest()) 88a6acbb31SJames Feist { 89a6acbb31SJames Feist BMCWEB_LOG_DEBUG << "Value for key " << key 90a6acbb31SJames Feist << " was less than min: " << __PRETTY_FUNCTION__; 91a6acbb31SJames Feist return false; 92a6acbb31SJames Feist } 93a6acbb31SJames Feist if constexpr (std::is_floating_point_v<ToType>) 94a6acbb31SJames Feist { 95ee344e0fSEd Tanous if (std::isnan(from)) 96a6acbb31SJames Feist { 97a6acbb31SJames Feist BMCWEB_LOG_DEBUG << "Value for key " << key << " was NAN"; 98a6acbb31SJames Feist return false; 99a6acbb31SJames Feist } 100a6acbb31SJames Feist } 101a6acbb31SJames Feist 102a6acbb31SJames Feist return true; 103a6acbb31SJames Feist } 104a6acbb31SJames Feist 105771cfa0fSJason M. Bills template <typename Type> 106471a5eb8SAppaRao Puli UnpackErrorCode unpackValueWithErrorCode(nlohmann::json& jsonValue, 107471a5eb8SAppaRao Puli const std::string& key, Type& value) 108771cfa0fSJason M. Bills { 109471a5eb8SAppaRao Puli UnpackErrorCode ret = UnpackErrorCode::success; 11041352c24SSantosh Puranik 111a6acbb31SJames Feist if constexpr (std::is_floating_point_v<Type>) 112771cfa0fSJason M. Bills { 113a6acbb31SJames Feist double helper = 0; 114a6acbb31SJames Feist double* jsonPtr = jsonValue.get_ptr<double*>(); 115771cfa0fSJason M. Bills 116771cfa0fSJason M. Bills if (jsonPtr == nullptr) 117771cfa0fSJason M. Bills { 118a6acbb31SJames Feist int64_t* intPtr = jsonValue.get_ptr<int64_t*>(); 119a6acbb31SJames Feist if (intPtr != nullptr) 120771cfa0fSJason M. Bills { 121a6acbb31SJames Feist helper = static_cast<double>(*intPtr); 122a6acbb31SJames Feist jsonPtr = &helper; 123771cfa0fSJason M. Bills } 124a6acbb31SJames Feist } 1255eb2bef2SAppaRao Puli if (jsonPtr == nullptr) 1265eb2bef2SAppaRao Puli { 127471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 1285eb2bef2SAppaRao Puli } 129cb13a392SEd Tanous if (!checkRange<Type>(*jsonPtr, key)) 130771cfa0fSJason M. Bills { 131471a5eb8SAppaRao Puli return UnpackErrorCode::outOfRange; 132771cfa0fSJason M. Bills } 133771cfa0fSJason M. Bills value = static_cast<Type>(*jsonPtr); 134771cfa0fSJason M. Bills } 135a6acbb31SJames Feist 136a6acbb31SJames Feist else if constexpr (std::is_signed_v<Type>) 137a6acbb31SJames Feist { 138a6acbb31SJames Feist int64_t* jsonPtr = jsonValue.get_ptr<int64_t*>(); 139271584abSEd Tanous if (jsonPtr == nullptr) 140271584abSEd Tanous { 141471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 142271584abSEd Tanous } 143cb13a392SEd Tanous if (!checkRange<Type>(*jsonPtr, key)) 144a6acbb31SJames Feist { 145471a5eb8SAppaRao Puli return UnpackErrorCode::outOfRange; 146a6acbb31SJames Feist } 147a6acbb31SJames Feist value = static_cast<Type>(*jsonPtr); 148a6acbb31SJames Feist } 149a6acbb31SJames Feist 1508102ddbaSAppaRao Puli else if constexpr ((std::is_unsigned_v<Type>)&&( 1518102ddbaSAppaRao Puli !std::is_same_v<bool, Type>)) 152a6acbb31SJames Feist { 153a6acbb31SJames Feist uint64_t* jsonPtr = jsonValue.get_ptr<uint64_t*>(); 154271584abSEd Tanous if (jsonPtr == nullptr) 155271584abSEd Tanous { 156471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 157271584abSEd Tanous } 158cb13a392SEd Tanous if (!checkRange<Type>(*jsonPtr, key)) 159a6acbb31SJames Feist { 160471a5eb8SAppaRao Puli return UnpackErrorCode::outOfRange; 161a6acbb31SJames Feist } 162a6acbb31SJames Feist value = static_cast<Type>(*jsonPtr); 163a6acbb31SJames Feist } 164a6acbb31SJames Feist 1650627a2c7SEd Tanous else if constexpr (std::is_same_v<nlohmann::json, Type>) 1660627a2c7SEd Tanous { 1670627a2c7SEd Tanous // Must be a complex type. Simple types (int string etc) should be 1680627a2c7SEd Tanous // unpacked directly 1698ebc91f6SEd Tanous if (!jsonValue.is_object() && !jsonValue.is_array() && 1708ebc91f6SEd Tanous !jsonValue.is_null()) 1710627a2c7SEd Tanous { 172471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 1730627a2c7SEd Tanous } 1740627a2c7SEd Tanous 1750627a2c7SEd Tanous value = std::move(jsonValue); 1760627a2c7SEd Tanous } 177471a5eb8SAppaRao Puli else 178471a5eb8SAppaRao Puli { 179471a5eb8SAppaRao Puli using JsonType = std::add_const_t<std::add_pointer_t<Type>>; 180471a5eb8SAppaRao Puli JsonType jsonPtr = jsonValue.get_ptr<JsonType>(); 181471a5eb8SAppaRao Puli if (jsonPtr == nullptr) 182471a5eb8SAppaRao Puli { 183471a5eb8SAppaRao Puli BMCWEB_LOG_DEBUG 184471a5eb8SAppaRao Puli << "Value for key " << key 185471a5eb8SAppaRao Puli << " was incorrect type: " << jsonValue.type_name(); 186471a5eb8SAppaRao Puli return UnpackErrorCode::invalidType; 187471a5eb8SAppaRao Puli } 188471a5eb8SAppaRao Puli value = std::move(*jsonPtr); 189471a5eb8SAppaRao Puli } 190471a5eb8SAppaRao Puli return ret; 191471a5eb8SAppaRao Puli } 192471a5eb8SAppaRao Puli 193471a5eb8SAppaRao Puli template <typename Type> 194471a5eb8SAppaRao Puli bool unpackValue(nlohmann::json& jsonValue, const std::string& key, 195471a5eb8SAppaRao Puli crow::Response& res, Type& value) 196471a5eb8SAppaRao Puli { 197471a5eb8SAppaRao Puli bool ret = true; 198471a5eb8SAppaRao Puli 1992c70f800SEd Tanous if constexpr (IsOptional<Type>::value) 200471a5eb8SAppaRao Puli { 201471a5eb8SAppaRao Puli value.emplace(); 202471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(jsonValue, key, res, 203471a5eb8SAppaRao Puli *value) && 204471a5eb8SAppaRao Puli ret; 205471a5eb8SAppaRao Puli } 2062c70f800SEd Tanous else if constexpr (IsStdArray<Type>::value) 207318226c2SJames Feist { 208318226c2SJames Feist if (!jsonValue.is_array()) 209318226c2SJames Feist { 210318226c2SJames Feist messages::propertyValueTypeError(res, res.jsonValue.dump(), key); 21141352c24SSantosh Puranik return false; 212318226c2SJames Feist } 213318226c2SJames Feist if (jsonValue.size() != value.size()) 214318226c2SJames Feist { 215318226c2SJames Feist messages::propertyValueTypeError(res, res.jsonValue.dump(), key); 21641352c24SSantosh Puranik return false; 217318226c2SJames Feist } 218318226c2SJames Feist size_t index = 0; 219318226c2SJames Feist for (const auto& val : jsonValue.items()) 220318226c2SJames Feist { 22141352c24SSantosh Puranik ret = unpackValue<typename Type::value_type>(val.value(), key, res, 22241352c24SSantosh Puranik value[index++]) && 22341352c24SSantosh Puranik ret; 224318226c2SJames Feist } 225318226c2SJames Feist } 2262c70f800SEd Tanous else if constexpr (IsVector<Type>::value) 227b1556427SEd Tanous { 228b1556427SEd Tanous if (!jsonValue.is_array()) 229b1556427SEd Tanous { 230b1556427SEd Tanous messages::propertyValueTypeError(res, res.jsonValue.dump(), key); 23141352c24SSantosh Puranik return false; 232b1556427SEd Tanous } 233b1556427SEd Tanous 234b1556427SEd Tanous for (const auto& val : jsonValue.items()) 235b1556427SEd Tanous { 236b1556427SEd Tanous value.emplace_back(); 23741352c24SSantosh Puranik ret = unpackValue<typename Type::value_type>(val.value(), key, res, 23841352c24SSantosh Puranik value.back()) && 23941352c24SSantosh Puranik ret; 240b1556427SEd Tanous } 241b1556427SEd Tanous } 242771cfa0fSJason M. Bills else 243771cfa0fSJason M. Bills { 244471a5eb8SAppaRao Puli UnpackErrorCode ec = unpackValueWithErrorCode(jsonValue, key, value); 245471a5eb8SAppaRao Puli if (ec != UnpackErrorCode::success) 246771cfa0fSJason M. Bills { 247471a5eb8SAppaRao Puli if (ec == UnpackErrorCode::invalidType) 248471a5eb8SAppaRao Puli { 249771cfa0fSJason M. Bills messages::propertyValueTypeError(res, jsonValue.dump(), key); 250471a5eb8SAppaRao Puli } 251471a5eb8SAppaRao Puli else if (ec == UnpackErrorCode::outOfRange) 252471a5eb8SAppaRao Puli { 253471a5eb8SAppaRao Puli messages::propertyValueNotInList(res, jsonValue.dump(), key); 254471a5eb8SAppaRao Puli } 25541352c24SSantosh Puranik return false; 256771cfa0fSJason M. Bills } 257771cfa0fSJason M. Bills } 258471a5eb8SAppaRao Puli 259471a5eb8SAppaRao Puli return ret; 260471a5eb8SAppaRao Puli } 261471a5eb8SAppaRao Puli 262471a5eb8SAppaRao Puli template <typename Type> 263471a5eb8SAppaRao Puli bool unpackValue(nlohmann::json& jsonValue, const std::string& key, Type& value) 264471a5eb8SAppaRao Puli { 265471a5eb8SAppaRao Puli bool ret = true; 2662c70f800SEd Tanous if constexpr (IsOptional<Type>::value) 267471a5eb8SAppaRao Puli { 268471a5eb8SAppaRao Puli value.emplace(); 269471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(jsonValue, key, *value) && 270471a5eb8SAppaRao Puli ret; 271471a5eb8SAppaRao Puli } 2722c70f800SEd Tanous else if constexpr (IsStdArray<Type>::value) 273471a5eb8SAppaRao Puli { 274471a5eb8SAppaRao Puli if (!jsonValue.is_array()) 275471a5eb8SAppaRao Puli { 276471a5eb8SAppaRao Puli return false; 277471a5eb8SAppaRao Puli } 278471a5eb8SAppaRao Puli if (jsonValue.size() != value.size()) 279471a5eb8SAppaRao Puli { 280471a5eb8SAppaRao Puli return false; 281471a5eb8SAppaRao Puli } 282471a5eb8SAppaRao Puli size_t index = 0; 283471a5eb8SAppaRao Puli for (const auto& val : jsonValue.items()) 284471a5eb8SAppaRao Puli { 285471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(val.value(), key, 286471a5eb8SAppaRao Puli value[index++]) && 287471a5eb8SAppaRao Puli ret; 288471a5eb8SAppaRao Puli } 289471a5eb8SAppaRao Puli } 2902c70f800SEd Tanous else if constexpr (IsVector<Type>::value) 291471a5eb8SAppaRao Puli { 292471a5eb8SAppaRao Puli if (!jsonValue.is_array()) 293471a5eb8SAppaRao Puli { 294471a5eb8SAppaRao Puli return false; 295471a5eb8SAppaRao Puli } 296471a5eb8SAppaRao Puli 297471a5eb8SAppaRao Puli for (const auto& val : jsonValue.items()) 298471a5eb8SAppaRao Puli { 299471a5eb8SAppaRao Puli value.emplace_back(); 300471a5eb8SAppaRao Puli ret = unpackValue<typename Type::value_type>(val.value(), key, 301471a5eb8SAppaRao Puli value.back()) && 302471a5eb8SAppaRao Puli ret; 303471a5eb8SAppaRao Puli } 304471a5eb8SAppaRao Puli } 305471a5eb8SAppaRao Puli else 306471a5eb8SAppaRao Puli { 307471a5eb8SAppaRao Puli UnpackErrorCode ec = unpackValueWithErrorCode(jsonValue, key, value); 308471a5eb8SAppaRao Puli if (ec != UnpackErrorCode::success) 309471a5eb8SAppaRao Puli { 310471a5eb8SAppaRao Puli return false; 311471a5eb8SAppaRao Puli } 312471a5eb8SAppaRao Puli } 313471a5eb8SAppaRao Puli 31441352c24SSantosh Puranik return ret; 315771cfa0fSJason M. Bills } 316771cfa0fSJason M. Bills 3179712f8acSEd Tanous template <size_t Count, size_t Index> 318cb13a392SEd Tanous bool readJsonValues(const std::string& key, nlohmann::json&, 319cb13a392SEd Tanous crow::Response& res, std::bitset<Count>&) 3209712f8acSEd Tanous { 3219712f8acSEd Tanous BMCWEB_LOG_DEBUG << "Unable to find variable for key" << key; 322a08b46ccSJason M. Bills messages::propertyUnknown(res, key); 32341352c24SSantosh Puranik return false; 3249712f8acSEd Tanous } 3259712f8acSEd Tanous 3269712f8acSEd Tanous template <size_t Count, size_t Index, typename ValueType, 3279712f8acSEd Tanous typename... UnpackTypes> 32841352c24SSantosh Puranik bool readJsonValues(const std::string& key, nlohmann::json& jsonValue, 3299712f8acSEd Tanous crow::Response& res, std::bitset<Count>& handled, 3309712f8acSEd Tanous const char* keyToCheck, ValueType& valueToFill, 3319712f8acSEd Tanous UnpackTypes&... in) 3329712f8acSEd Tanous { 33341352c24SSantosh Puranik bool ret = true; 3349712f8acSEd Tanous if (key != keyToCheck) 3359712f8acSEd Tanous { 33641352c24SSantosh Puranik ret = readJsonValues<Count, Index + 1>(key, jsonValue, res, handled, 33741352c24SSantosh Puranik in...) && 33841352c24SSantosh Puranik ret; 33941352c24SSantosh Puranik return ret; 3409712f8acSEd Tanous } 3419712f8acSEd Tanous 3429712f8acSEd Tanous handled.set(Index); 3439712f8acSEd Tanous 34441352c24SSantosh Puranik return unpackValue<ValueType>(jsonValue, key, res, valueToFill) && ret; 3459712f8acSEd Tanous } 3469712f8acSEd Tanous 3479712f8acSEd Tanous template <size_t Index = 0, size_t Count> 348cb13a392SEd Tanous bool handleMissing(std::bitset<Count>&, crow::Response&) 3499712f8acSEd Tanous { 35041352c24SSantosh Puranik return true; 3519712f8acSEd Tanous } 3529712f8acSEd Tanous 3539712f8acSEd Tanous template <size_t Index = 0, size_t Count, typename ValueType, 3549712f8acSEd Tanous typename... UnpackTypes> 35541352c24SSantosh Puranik bool handleMissing(std::bitset<Count>& handled, crow::Response& res, 356cb13a392SEd Tanous const char* key, ValueType&, UnpackTypes&... in) 3579712f8acSEd Tanous { 35841352c24SSantosh Puranik bool ret = true; 3592c70f800SEd Tanous if (!handled.test(Index) && !IsOptional<ValueType>::value) 3609712f8acSEd Tanous { 36141352c24SSantosh Puranik ret = false; 362a08b46ccSJason M. Bills messages::propertyMissing(res, key); 3639712f8acSEd Tanous } 36441352c24SSantosh Puranik return details::handleMissing<Index + 1, Count>(handled, res, in...) && ret; 3659712f8acSEd Tanous } 3669712f8acSEd Tanous } // namespace details 3679712f8acSEd Tanous 3689712f8acSEd Tanous template <typename... UnpackTypes> 3690627a2c7SEd Tanous bool readJson(nlohmann::json& jsonRequest, crow::Response& res, const char* key, 3709712f8acSEd Tanous UnpackTypes&... in) 3719712f8acSEd Tanous { 37241352c24SSantosh Puranik bool result = true; 3739712f8acSEd Tanous if (!jsonRequest.is_object()) 3749712f8acSEd Tanous { 3759712f8acSEd Tanous BMCWEB_LOG_DEBUG << "Json value is not an object"; 376f12894f8SJason M. Bills messages::unrecognizedRequestBody(res); 3779712f8acSEd Tanous return false; 3789712f8acSEd Tanous } 3799712f8acSEd Tanous 3809712f8acSEd Tanous if (jsonRequest.empty()) 3819712f8acSEd Tanous { 3829712f8acSEd Tanous BMCWEB_LOG_DEBUG << "Json value is empty"; 383f12894f8SJason M. Bills messages::emptyJSON(res); 3849712f8acSEd Tanous return false; 3859712f8acSEd Tanous } 3869712f8acSEd Tanous 3879712f8acSEd Tanous std::bitset<(sizeof...(in) + 1) / 2> handled(0); 3889712f8acSEd Tanous for (const auto& item : jsonRequest.items()) 3899712f8acSEd Tanous { 39041352c24SSantosh Puranik result = 3919712f8acSEd Tanous details::readJsonValues<(sizeof...(in) + 1) / 2, 0, UnpackTypes...>( 39241352c24SSantosh Puranik item.key(), item.value(), res, handled, key, in...) && 39341352c24SSantosh Puranik result; 3949712f8acSEd Tanous } 3959712f8acSEd Tanous 39641352c24SSantosh Puranik BMCWEB_LOG_DEBUG << "JSON result is: " << result; 3979712f8acSEd Tanous 39841352c24SSantosh Puranik return details::handleMissing(handled, res, key, in...) && result; 3999712f8acSEd Tanous } 40077dd8813SKowalski, Kamil 4010627a2c7SEd Tanous template <typename... UnpackTypes> 4020627a2c7SEd Tanous bool readJson(const crow::Request& req, crow::Response& res, const char* key, 4030627a2c7SEd Tanous UnpackTypes&... in) 4040627a2c7SEd Tanous { 4050627a2c7SEd Tanous nlohmann::json jsonRequest; 4060627a2c7SEd Tanous if (!json_util::processJsonFromRequest(res, req, jsonRequest)) 4070627a2c7SEd Tanous { 4080627a2c7SEd Tanous BMCWEB_LOG_DEBUG << "Json value not readable"; 4090627a2c7SEd Tanous return false; 4100627a2c7SEd Tanous } 4110627a2c7SEd Tanous return readJson(jsonRequest, res, key, in...); 4120627a2c7SEd Tanous } 4130627a2c7SEd Tanous 414471a5eb8SAppaRao Puli template <typename Type> 415471a5eb8SAppaRao Puli bool getValueFromJsonObject(nlohmann::json& jsonData, const std::string& key, 416471a5eb8SAppaRao Puli Type& value) 417471a5eb8SAppaRao Puli { 418471a5eb8SAppaRao Puli nlohmann::json jsonValue = jsonData[key]; 419471a5eb8SAppaRao Puli if (jsonValue.is_null()) 420471a5eb8SAppaRao Puli { 421471a5eb8SAppaRao Puli BMCWEB_LOG_DEBUG << "Key " << key << " not exist"; 422471a5eb8SAppaRao Puli return false; 423471a5eb8SAppaRao Puli } 424471a5eb8SAppaRao Puli 425471a5eb8SAppaRao Puli return details::unpackValue(jsonValue, key, value); 426471a5eb8SAppaRao Puli } 427471a5eb8SAppaRao Puli 42877dd8813SKowalski, Kamil } // namespace json_util 42977dd8813SKowalski, Kamil } // namespace redfish 430