xref: /openbmc/bmcweb/features/redfish/src/utils/json_utils.cpp (revision 77dd8813e9a1f2baec63d959de15af39a8cd12d0)
1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include "utils/json_utils.hpp"
17 #include <error_messages.hpp>
18 #include <crow/http_codes.h>
19 
20 namespace redfish {
21 
22 namespace json_util {
23 
24 Result getString(const char* fieldName, const nlohmann::json& json,
25                  const std::string*& output) {
26   // Find field
27   auto fieldIt = json.find(fieldName);
28 
29   // Verify existence
30   if (fieldIt == json.end()) {
31     return Result::NOT_EXIST;
32   }
33 
34   output = fieldIt->get_ptr<const std::string*>();
35 
36   // Verify type - we know that it exists, so nullptr means wrong type
37   if (output == nullptr) {
38     return Result::WRONG_TYPE;
39   }
40 
41   return Result::SUCCESS;
42 }
43 
44 Result getObject(const char* fieldName, const nlohmann::json& json,
45                  nlohmann::json* output) {
46   // Verify input pointer
47   if (output == nullptr) {
48     return Result::NULL_POINTER;
49   }
50 
51   // Find field
52   auto fieldIt = json.find(fieldName);
53 
54   // Verify existence
55   if (fieldIt == json.end()) {
56     return Result::NOT_EXIST;
57   }
58 
59   // Verify type
60   if (!fieldIt->is_object()) {
61     return Result::WRONG_TYPE;
62   }
63 
64   // Extract value
65   *output = *fieldIt;
66 
67   return Result::SUCCESS;
68 }
69 
70 Result getArray(const char* fieldName, const nlohmann::json& json,
71                 nlohmann::json* output) {
72   // Verify input pointer
73   if (output == nullptr) {
74     return Result::NULL_POINTER;
75   }
76 
77   // Find field
78   auto fieldIt = json.find(fieldName);
79 
80   // Verify existence
81   if (fieldIt == json.end()) {
82     return Result::NOT_EXIST;
83   }
84 
85   // Verify type
86   if (!fieldIt->is_array()) {
87     return Result::WRONG_TYPE;
88   }
89 
90   // Extract value
91   *output = *fieldIt;
92 
93   return Result::SUCCESS;
94 }
95 
96 Result getInt(const char* fieldName, const nlohmann::json& json,
97               int64_t& output) {
98   // Find field
99   auto fieldIt = json.find(fieldName);
100 
101   // Verify existence
102   if (fieldIt == json.end()) {
103     return Result::NOT_EXIST;
104   }
105 
106   const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
107 
108   // Verify type - we know that it exists, so nullptr means wrong type
109   if (retVal == nullptr) {
110     return Result::WRONG_TYPE;
111   }
112 
113   // Extract value
114   output = *retVal;
115 
116   return Result::SUCCESS;
117 }
118 
119 Result getUnsigned(const char* fieldName, const nlohmann::json& json,
120                    uint64_t& output) {
121   // Find field
122   auto fieldIt = json.find(fieldName);
123 
124   // Verify existence
125   if (fieldIt == json.end()) {
126     return Result::NOT_EXIST;
127   }
128 
129   const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
130 
131   // Verify type - we know that it exists, so nullptr means wrong type
132   if (retVal == nullptr) {
133     return Result::WRONG_TYPE;
134   }
135 
136   // Extract value
137   output = *retVal;
138 
139   return Result::SUCCESS;
140 }
141 
142 Result getBool(const char* fieldName, const nlohmann::json& json,
143                bool& output) {
144   // Find field
145   auto fieldIt = json.find(fieldName);
146 
147   // Verify existence
148   if (fieldIt == json.end()) {
149     return Result::NOT_EXIST;
150   }
151 
152   const bool* retVal = fieldIt->get_ptr<const bool*>();
153 
154   // Verify type - we know that it exists, so nullptr means wrong type
155   if (retVal == nullptr) {
156     return Result::WRONG_TYPE;
157   }
158 
159   // Extract value
160   output = *retVal;
161 
162   return Result::SUCCESS;
163 }
164 
165 Result getDouble(const char* fieldName, const nlohmann::json& json,
166                  double& output) {
167   // Find field
168   auto fieldIt = json.find(fieldName);
169 
170   // Verify existence
171   if (fieldIt == json.end()) {
172     return Result::NOT_EXIST;
173   }
174 
175   const double* retVal = fieldIt->get_ptr<const double*>();
176 
177   // Verify type - we know that it exists, so nullptr means wrong type
178   if (retVal == nullptr) {
179     return Result::WRONG_TYPE;
180   }
181 
182   // Extract value
183   output = *retVal;
184 
185   return Result::SUCCESS;
186 }
187 
188 Result getString(const char* fieldName, const nlohmann::json& json,
189                  const std::string*& output, uint8_t msgCfgMap,
190                  nlohmann::json& msgJson, const std::string&& fieldPath) {
191   // Find field
192   auto fieldIt = json.find(fieldName);
193 
194   // Verify existence
195   if (fieldIt == json.end()) {
196     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
197       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
198                                  fieldPath);
199     }
200 
201     return Result::NOT_EXIST;
202   }
203 
204   output = fieldIt->get_ptr<const std::string*>();
205 
206   // Verify type - we know that it exists, so nullptr means wrong type
207   if (output == nullptr) {
208     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
209       messages::addMessageToJson(
210           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
211           fieldPath);
212     }
213 
214     return Result::WRONG_TYPE;
215   }
216 
217   return Result::SUCCESS;
218 }
219 
220 Result getObject(const char* fieldName, const nlohmann::json& json,
221                  nlohmann::json* output, uint8_t msgCfgMap,
222                  nlohmann::json& msgJson, const std::string&& fieldPath) {
223   // Verify input pointer
224   if (output == nullptr) {
225     return Result::NULL_POINTER;
226   }
227 
228   // Find field
229   auto fieldIt = json.find(fieldName);
230 
231   // Verify existence
232   if (fieldIt == json.end()) {
233     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
234       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
235                                  fieldPath);
236     }
237 
238     return Result::NOT_EXIST;
239   }
240 
241   // Verify type
242   if (!fieldIt->is_object()) {
243     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
244       messages::addMessageToJson(
245           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
246           fieldPath);
247     }
248 
249     return Result::WRONG_TYPE;
250   }
251 
252   // Extract value
253   *output = *fieldIt;
254 
255   return Result::SUCCESS;
256 }
257 
258 Result getArray(const char* fieldName, const nlohmann::json& json,
259                 nlohmann::json* output, uint8_t msgCfgMap,
260                 nlohmann::json& msgJson, const std::string&& fieldPath) {
261   // Verify input pointer
262   if (output == nullptr) {
263     return Result::NULL_POINTER;
264   }
265 
266   // Find field
267   auto fieldIt = json.find(fieldName);
268 
269   // Verify existence
270   if (fieldIt == json.end()) {
271     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
272       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
273                                  fieldPath);
274     }
275 
276     return Result::NOT_EXIST;
277   }
278 
279   // Verify type
280   if (!fieldIt->is_array()) {
281     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
282       messages::addMessageToJson(
283           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
284           fieldPath);
285     }
286 
287     return Result::WRONG_TYPE;
288   }
289 
290   // Extract value
291   *output = *fieldIt;
292 
293   return Result::SUCCESS;
294 }
295 
296 Result getInt(const char* fieldName, const nlohmann::json& json,
297               int64_t& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
298               const std::string&& fieldPath) {
299   // Find field
300   auto fieldIt = json.find(fieldName);
301 
302   // Verify existence
303   if (fieldIt == json.end()) {
304     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
305       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
306                                  fieldPath);
307     }
308 
309     return Result::NOT_EXIST;
310   }
311 
312   const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
313 
314   // Verify type - we know that it exists, so nullptr means wrong type
315   if (retVal == nullptr) {
316     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
317       messages::addMessageToJson(
318           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
319           fieldPath);
320     }
321 
322     return Result::WRONG_TYPE;
323   }
324 
325   // Extract value
326   output = *retVal;
327 
328   return Result::SUCCESS;
329 }
330 
331 Result getUnsigned(const char* fieldName, const nlohmann::json& json,
332                    uint64_t& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
333                    const std::string&& fieldPath) {
334   // Find field
335   auto fieldIt = json.find(fieldName);
336 
337   // Verify existence
338   if (fieldIt == json.end()) {
339     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
340       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
341                                  fieldPath);
342     }
343 
344     return Result::NOT_EXIST;
345   }
346 
347   const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
348 
349   // Verify type - we know that it exists, so nullptr means wrong type
350   if (retVal == nullptr) {
351     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
352       messages::addMessageToJson(
353           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
354           fieldPath);
355     }
356 
357     return Result::WRONG_TYPE;
358   }
359 
360   // Extract value
361   output = *retVal;
362 
363   return Result::SUCCESS;
364 }
365 
366 Result getBool(const char* fieldName, const nlohmann::json& json, bool& output,
367                uint8_t msgCfgMap, nlohmann::json& msgJson,
368                const std::string&& fieldPath) {
369   // Find field
370   auto fieldIt = json.find(fieldName);
371 
372   // Verify existence
373   if (fieldIt == json.end()) {
374     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
375       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
376                                  fieldPath);
377     }
378 
379     return Result::NOT_EXIST;
380   }
381 
382   const bool* retVal = fieldIt->get_ptr<const bool*>();
383 
384   // Verify type - we know that it exists, so nullptr means wrong type
385   if (retVal == nullptr) {
386     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
387       messages::addMessageToJson(
388           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
389           fieldPath);
390     }
391 
392     return Result::WRONG_TYPE;
393   }
394 
395   // Extract value
396   output = *retVal;
397 
398   return Result::SUCCESS;
399 }
400 
401 Result getDouble(const char* fieldName, const nlohmann::json& json,
402                  double& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
403                  const std::string&& fieldPath) {
404   // Find field
405   auto fieldIt = json.find(fieldName);
406 
407   // Verify existence
408   if (fieldIt == json.end()) {
409     if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
410       messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
411                                  fieldPath);
412     }
413 
414     return Result::NOT_EXIST;
415   }
416 
417   const double* retVal = fieldIt->get_ptr<const double*>();
418 
419   // Verify type - we know that it exists, so nullptr means wrong type
420   if (retVal == nullptr) {
421     if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
422       messages::addMessageToJson(
423           msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
424           fieldPath);
425     }
426 
427     return Result::WRONG_TYPE;
428   }
429 
430   // Extract value
431   output = *retVal;
432 
433   return Result::SUCCESS;
434 }
435 
436 bool processJsonFromRequest(crow::response& res, const crow::request& req,
437                             nlohmann::json& reqJson) {
438   reqJson = nlohmann::json::parse(req.body, nullptr, false);
439 
440   if (reqJson.is_discarded()) {
441     messages::addMessageToErrorJson(res.json_value, messages::malformedJSON());
442 
443     res.code = static_cast<int>(HttpRespCode::BAD_REQUEST);
444     res.end();
445 
446     return false;
447   }
448 
449   return true;
450 }
451 
452 }  // namespace json_util
453 
454 }  // namespace redfish
455