xref: /openbmc/bmcweb/features/redfish/include/utils/json_utils.hpp (revision 1214b7e7d921e331fb1480c7e5d579ffa5811cda)
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