bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
JsonUtils.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2//
3// This file is part of cmr_module, A C++ module that can be loaded in to
4// the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
5//
6// Copyright (c) 2018 OPeNDAP, Inc.
7// Author: Nathan Potter <ndp@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24//
25#include <sstream>
26#include <fstream>
27
28#include "nlohmann/json.hpp"
29
30#include "BESError.h"
31#include "BESDebug.h"
32#include "BESUtil.h"
33#include "RemoteResource.h"
34
35#include "CmrNames.h"
36#include "CmrNotFoundError.h"
37#include "CmrInternalError.h"
38
39#include "JsonUtils.h"
40
41using namespace std;
42using json = nlohmann::json;
43
44#define prolog std::string("JsonUtils::").append(__func__).append("() - ")
45
46std::string truth(bool t){ if(t){return "true";} return "false"; }
47
48namespace cmr {
58json JsonUtils::get_as_json(const string &url) const
59{
60 BESDEBUG(MODULE,prolog << "Trying url: " << url << endl);
61 http::RemoteResource remoteResource(make_shared<http::url>(url));
62 remoteResource.retrieve_resource();
63 std::ifstream f(remoteResource.get_filename());
64 json data = json::parse(f);
65 return data;
66}
67
73std::string JsonUtils::typeName(unsigned int t)
74{
75 const char* tnames[] =
76 { "Null", "False", "True", "Object", "Array", "String", "Number" };
77 return string(tnames[t]);
78}
79
86double JsonUtils::qc_double(const std::string &key, const nlohmann::json &json_obj) const
87{
88 double value=0.0;
89
90 BESDEBUG(MODULE, prolog << "Key: '" << key << "' JSON: " << endl << json_obj.dump(2) << endl);
91 // Check input for object.
92 bool result = json_obj.is_object();
93 string msg0 = prolog + "Json document is" + (result?"":" NOT") + " an object.";
94 BESDEBUG(MODULE, msg0 << endl);
95 if(!result){
96 return value;
97 }
98 const auto &key_itr = json_obj.find(key);
99 if(key_itr == json_obj.end()){
100 stringstream msg;
101 msg << prolog;
102 msg << "Ouch! Unable to locate the '" << key;
103 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
104 BESDEBUG(MODULE, msg.str() << endl);
105 return value;
106 }
107
108 auto &dobj = json_obj[key];
109 if(dobj.is_null()){
110 stringstream msg;
111 msg << prolog;
112 msg << "Failed to locate the '" << key;
113 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
114 BESDEBUG(MODULE, msg.str() << endl);
115 return value;
116 }
117 if(!dobj.is_number_float() && !dobj.is_number()){
118 stringstream msg;
119 msg << prolog;
120 msg << "The child element called '" << key;
121 msg << "' is not a floating point value. json: " << endl << json_obj.dump(2) << endl;
122 BESDEBUG(MODULE, msg.str() << endl);
123 return value;
124 }
125 return dobj.get<double>();
126
127
128}
129
136bool JsonUtils::qc_boolean(const std::string &key, const nlohmann::json &json_obj) const
137{
138 bool value=false;
139
140 BESDEBUG(MODULE, prolog << "Key: '" << key << "' JSON: " << endl << json_obj.dump(2) << endl);
141 // Check input for object.
142 bool result = json_obj.is_object();
143 string msg0 = prolog + "Json document is" + (result?"":" NOT") + " an object.";
144 BESDEBUG(MODULE, msg0 << endl);
145 if(!result){
146 return value;
147 }
148 const auto &key_itr = json_obj.find(key);
149 if(key_itr == json_obj.end()){
150 stringstream msg;
151 msg << prolog;
152 msg << "Ouch! Unable to locate the '" << key;
153 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
154 BESDEBUG(MODULE, msg.str() << endl);
155 return value;
156 }
157
158 auto &dobj = json_obj[key];
159 if(dobj.is_null()){
160 stringstream msg;
161 msg << prolog;
162 msg << "Failed to locate the '" << key;
163 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
164 BESDEBUG(MODULE, msg.str() << endl);
165 return value;
166 }
167 if(!dobj.is_boolean()){
168 stringstream msg;
169 msg << prolog;
170 msg << "The child element called '" << key;
171 msg << "' is not boolean valued. json: " << endl << json_obj.dump(2) << endl;
172 BESDEBUG(MODULE, msg.str() << endl);
173 return value;
174 }
175 return dobj.get<bool>();
176
177
178}
179
180
187unsigned long int JsonUtils::qc_integer(const std::string &key, const nlohmann::json &json_obj) const
188{
189 unsigned long int value=0;
190
191 BESDEBUG(MODULE, prolog << "Key: '" << key << "' JSON: " << endl << json_obj.dump(2) << endl);
192 // Check input for object.
193 bool result = json_obj.is_object();
194 string msg0 = prolog + "Json document is" + (result?"":" NOT") + " an object.";
195 BESDEBUG(MODULE, msg0 << endl);
196 if(!result){
197 return value;
198 }
199 const auto &key_itr = json_obj.find(key);
200 if(key_itr == json_obj.end()){
201 stringstream msg;
202 msg << prolog;
203 msg << "Ouch! Unable to locate the '" << key;
204 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
205 BESDEBUG(MODULE, msg.str() << endl);
206 return value;
207 }
208
209 auto &dobj = json_obj[key];
210 if(dobj.is_null()){
211 stringstream msg;
212 msg << prolog;
213 msg << "Failed to locate the '" << key;
214 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
215 BESDEBUG(MODULE, msg.str() << endl);
216 return value;
217 }
218 if(!dobj.is_number_unsigned()){
219 stringstream msg;
220 msg << prolog;
221 msg << "The child element called '" << key;
222 msg << "' is not unsigned integer valued. json: " << endl << json_obj.dump(2) << endl;
223 BESDEBUG(MODULE, msg.str() << endl);
224 return value;
225 }
226 return dobj.get<unsigned long>();
227}
228
229
230
237std::string JsonUtils::get_str_if_present(const std::string &key, const nlohmann::json& json_obj) const
238{
239 const string empty_string;
240
241 BESDEBUG(MODULE, prolog << "Key: '" << key << "' JSON: " << endl << json_obj.dump(2) << endl);
242 // Check input for object.
243 bool result = json_obj.is_object();
244 string msg0 = prolog + "Json document is" + (result?"":" NOT") + " an object.";
245 BESDEBUG(MODULE, msg0 << endl);
246 if(!result){
247 return empty_string;
248 }
249
250 const auto &key_itr = json_obj.find(key);
251 if(key_itr == json_obj.end()){
252 stringstream msg;
253 msg << prolog;
254 msg << "Ouch! Unable to locate the '" << key;
255 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
256 BESDEBUG(MODULE, msg.str() << endl);
257 return empty_string;
258 }
259
260 auto &string_obj = json_obj[key];
261 if(string_obj.is_null()){
262 stringstream msg;
263 msg << prolog;
264 msg << "Failed to locate the '" << key;
265 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
266 BESDEBUG(MODULE, msg.str() << endl);
267 return empty_string;
268 }
269 if(!string_obj.is_string()){
270 stringstream msg;
271 msg << prolog;
272 msg << "The child element called '" << key;
273 msg << "' is not a string. json: " << endl << json_obj.dump(2) << endl;
274 BESDEBUG(MODULE, msg.str() << endl);
275 return empty_string;
276 }
277 return string_obj.get<string>();
278
279
280}
281
288const nlohmann::json& JsonUtils::qc_get_array(const std::string &key, const nlohmann::json& json_obj) const
289{
290 BESDEBUG(MODULE, prolog << "Key: '" << key << "' JSON: " << endl << json_obj.dump(2) << endl);
291 // Check input for object.
292 bool result = json_obj.is_object();
293 string msg0 = prolog + "Json document is" + (result?"":" NOT") + " an object.";
294 BESDEBUG(MODULE, msg0 << endl);
295 if(!result){
296 throw CmrInternalError(msg0, __FILE__, __LINE__);
297 }
298
299 const auto &key_itr = json_obj.find(key);
300 if(key_itr == json_obj.end()){
301 stringstream msg;
302 msg << prolog;
303 msg << "Ouch! Unable to locate the '" << key;
304 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
305 BESDEBUG(MODULE, msg.str() << endl);
306 throw CmrNotFoundError(msg.str(), __FILE__, __LINE__);
307 }
308
309 auto &array_obj = json_obj[key];
310 if(array_obj.is_null()){
311 stringstream msg;
312 msg << prolog;
313 msg << "Ouch! Unable to locate the '" << key;
314 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
315 BESDEBUG(MODULE, msg.str() << endl);
316 throw CmrNotFoundError(msg.str(), __FILE__, __LINE__);
317 }
318 if(!array_obj.is_array()){
319 stringstream msg;
320 msg << prolog;
321 msg << "ERROR: The child element called '" << key;
322 msg << "' is not an array. json: " << endl << json_obj.dump(2) << endl;
323 BESDEBUG(MODULE, msg.str() << endl);
324 throw CmrInternalError(msg.str(), __FILE__, __LINE__);
325 }
326 return array_obj;
327}
328
335const nlohmann::json& JsonUtils::qc_get_object(const std::string &key, const nlohmann::json& json_obj) const
336{
337 BESDEBUG(MODULE, prolog << "Key: '" << key << "' JSON: " << endl << json_obj.dump(2) << endl);
338
339 // Check input for object.
340 bool result = json_obj.is_object();
341 string msg0 = prolog + "Json document is" + (result?"":" NOT") + " an object.";
342 BESDEBUG(MODULE, msg0 << endl);
343 if(!result){
344 throw CmrInternalError(msg0, __FILE__, __LINE__);
345 }
346
347 const auto &key_itr = json_obj.find(key);
348 if(key_itr == json_obj.end()){
349 stringstream msg;
350 msg << prolog;
351 msg << "Ouch! Unable to locate the '" << key;
352 msg << "' child of json: " << endl << json_obj.dump(2) << endl;
353 BESDEBUG(MODULE, msg.str() << endl);
354 throw CmrNotFoundError(msg.str(), __FILE__, __LINE__);
355 }
356
357 auto &child_obj = json_obj[key];
358
359 if(child_obj.is_null()){
360 stringstream msg;
361 msg << prolog;
362 msg << "Ouch! Unable to locate the '" << key;
363 msg << "' child of json: " << endl << child_obj.dump(2) << endl;
364 BESDEBUG(MODULE, msg.str() << endl);
365 throw CmrNotFoundError(msg.str(), __FILE__, __LINE__);
366 }
367 if(!child_obj.is_object()){
368 stringstream msg;
369 msg << prolog;
370 msg << "ERROR: The child element called '" << key;
371 msg << "' is not an object. json: " << endl << child_obj.dump(2) << endl;
372 BESDEBUG(MODULE, msg.str() << endl);
373 throw CmrInternalError(msg.str(), __FILE__, __LINE__);
374 }
375 return child_obj;
376}
377
383std::string JsonUtils::probe_json(const nlohmann::json &j) const
384{
385 string hdr0("#########################################################################################");
386 string hdr1("#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
387
388 stringstream msg;
389 msg << endl;
390 msg << hdr0 << endl;
391 msg << j.dump(2) << endl;
392 msg << hdr1 << endl;
393 msg << " j.is_null(): " << truth(j.is_null()) << endl;
394 msg << " j.is_object(): " << truth(j.is_object()) << endl;
395 msg << " j.is_array(): " << truth(j.is_array()) << endl;
396 msg << endl;
397 msg << " j.is_discarded(): " << truth(j.is_discarded()) << endl;
398 msg << " j.is_string(): " << truth(j.is_string()) << endl;
399 msg << " j.is_structured(): " << truth(j.is_structured()) << endl;
400 msg << " j.is_binary(): " << truth(j.is_binary()) << endl;
401 msg << " j.is_boolean(): " << truth(j.is_boolean()) << endl;
402 msg << " j.is_number(): " << truth(j.is_number()) << endl;
403 msg << " j.is_number_float(): " << truth(j.is_number_float()) << endl;
404 msg << " j.is_number_integer(): " << truth(j.is_number_integer()) << endl;
405 msg << "j.is_number_unsigned(): " << truth(j.is_number_unsigned()) << endl;
406 msg << " j.is_primitive(): " << truth(j.is_primitive()) << endl;
407 msg << " j.size(): " << j.size()<< endl;
408 msg << " j.empty(): " << truth(j.empty()) << endl;
409
410 msg << hdr0 << endl;
411 return msg.str();
412}
413
414
415
416} // namespace cmr
bool qc_boolean(const std::string &key, const nlohmann::json &json_obj) const
Definition JsonUtils.cc:136
static std::string typeName(unsigned int t)
Definition JsonUtils.cc:73
std::string get_str_if_present(const std::string &key, const nlohmann::json &json_obj) const
Definition JsonUtils.cc:237
nlohmann::json get_as_json(const std::string &url) const
Definition JsonUtils.cc:58
double qc_double(const std::string &key, const nlohmann::json &json_obj) const
Definition JsonUtils.cc:86
std::string probe_json(const nlohmann::json &j) const
Definition JsonUtils.cc:383
unsigned long int qc_integer(const std::string &key, const nlohmann::json &json_obj) const
Definition JsonUtils.cc:187
const nlohmann::json & qc_get_array(const std::string &key, const nlohmann::json &json_obj) const
Definition JsonUtils.cc:288
const nlohmann::json & qc_get_object(const std::string &key, const nlohmann::json &json_obj) const
Definition JsonUtils.cc:335
std::string get_filename() const
Returns the file name in which the content of the URL has been stored.