libpromeki main
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
json.h
Go to the documentation of this file.
1
9#pragma once
10
12#include <promeki/core/string.h>
15#include <promeki/thirdparty/nlohmann/json.hpp>
16
18
19class JsonArray;
20
46 public:
49
56 static JsonObject parse(const String &str, Error *err = nullptr) {
58 try {
59 ret._j = nlohmann::json::parse(str.str());
60 if(!ret._j.is_object()) throw std::runtime_error("not an object");
61 if(err) *err = Error::Ok;
62 } catch(...) {
63 ret._j = nlohmann::json::object();
64 if(err) *err = Error::Invalid;
65 }
66 return ret;
67 }
68
70 JsonObject() : _j(nlohmann::json::object()) {}
71
73 int size() const { return static_cast<int>(_j.size()); }
74
76 bool isValid() const { return size() > 0; }
77
83 bool valueIsNull(const String &key) const {
84 auto it = _j.find(key.str());
85 return it != _j.end() && it->is_null();
86 }
87
93 bool valueIsObject(const String &key) const {
94 auto it = _j.find(key.str());
95 return it != _j.end() && it->is_object();
96 }
97
103 bool valueIsArray(const String &key) const {
104 auto it = _j.find(key.str());
105 return it != _j.end() && it->is_array();
106 }
107
113 bool contains(const String &key) const { return _j.contains(key.str()); }
114
121 bool getBool(const String &key, Error *err = nullptr) const { return get<bool>(key, err); }
122
129 int64_t getInt(const String &key, Error *err = nullptr) const { return get<int64_t>(key, err); }
130
137 uint64_t getUInt(const String &key, Error *err = nullptr) const { return get<uint64_t>(key, err); }
138
145 double getDouble(const String &key, Error *err = nullptr) const { return get<double>(key, err); }
146
153 String getString(const String &key, Error *err = nullptr) const { return get<std::string>(key, err); }
154
161 JsonObject getObject(const String &key, Error *err = nullptr) const {
162 auto it = _j.find(key.str());
163 if(it == _j.end() || !it->is_object()) {
164 if(err) *err = Error::Invalid;
165 return JsonObject();
166 }
167 if(err) *err = Error::Ok;
169 ret._j = *it;
170 return ret;
171 }
172
179 inline JsonArray getArray(const String &key, Error *err = nullptr) const;
180
186 String toString(unsigned int indent = 0) const {
187 if(indent == 0) return _j.dump();
188 return _j.dump(static_cast<int>(indent));
189 }
190
192 void clear() { _j.clear(); }
193
198 void setNull(const String &key) { _j[key.str()] = nullptr; }
199
205 void set(const String &key, const JsonObject &val) { _j[key.str()] = val._j; }
206
212 inline void set(const String &key, const JsonArray &val);
213
215 void set(const String &key, bool val) { _j[key.str()] = val; }
217 void set(const String &key, int val) { _j[key.str()] = val; }
219 void set(const String &key, unsigned int val) { _j[key.str()] = val; }
221 void set(const String &key, int64_t val) { _j[key.str()] = val; }
223 void set(const String &key, uint64_t val) { _j[key.str()] = val; }
225 void set(const String &key, float val) { _j[key.str()] = val; }
227 void set(const String &key, double val) { _j[key.str()] = val; }
229 void set(const String &key, const char *val) { _j[key.str()] = std::string(val); }
231 void set(const String &key, const String &val) { _j[key.str()] = val.str(); }
233 void set(const String &key, const UUID &val) { _j[key.str()] = val.toString().str(); }
234
240 void setFromVariant(const String &key, const Variant &val) {
241 const auto &k = key.str();
242 switch(val.type()) {
243 case Variant::TypeInvalid: _j[k] = nullptr; break;
244 case Variant::TypeBool: _j[k] = val.get<bool>(); break;
245 case Variant::TypeU8: _j[k] = val.get<uint8_t>(); break;
246 case Variant::TypeS8: _j[k] = val.get<int8_t>(); break;
247 case Variant::TypeU16: _j[k] = val.get<uint16_t>(); break;
248 case Variant::TypeS16: _j[k] = val.get<int16_t>(); break;
249 case Variant::TypeU32: _j[k] = val.get<uint32_t>(); break;
250 case Variant::TypeS32: _j[k] = val.get<int32_t>(); break;
251 case Variant::TypeU64: _j[k] = val.get<uint64_t>(); break;
252 case Variant::TypeS64: _j[k] = val.get<int64_t>(); break;
253 case Variant::TypeFloat: _j[k] = val.get<float>(); break;
254 case Variant::TypeDouble: _j[k] = val.get<double>(); break;
255 default: _j[k] = val.get<String>().str(); break;
256 }
257 }
258
264 template <typename Func> void forEach(Func &&func) const {
265 for(auto it = _j.begin(); it != _j.end(); ++it) {
266 String key = it.key();
267 Variant val = Variant::fromJson(it.value());
268 func(key, val);
269 }
270 }
271
273 bool operator==(const JsonObject &other) const { return _j == other._j; }
274
275 private:
276 friend class JsonArray;
277
279
280 template <typename T>
281 T get(const String &key, Error *err = nullptr) const {
282 auto it = _j.find(key.str());
283 if(it == _j.end()) {
284 if(err) *err = Error::Invalid;
285 return T{};
286 }
287 return getVal<T>(*it, err);
288 }
289
290 template <typename T>
291 static T getVal(const nlohmann::json &val, Error *err) {
292 T ret{};
293 bool good = false;
294 try {
295 if constexpr (std::is_same_v<T, bool>) {
296 if(val.is_boolean()) { ret = val.get<bool>(); good = true; }
297 else if(val.is_number_integer()) { ret = val.get<int64_t>() != 0; good = true; }
298 } else if constexpr (std::is_integral_v<T>) {
299 if(val.is_number()) { ret = static_cast<T>(val.get<int64_t>()); good = true; }
300 else if(val.is_boolean()) { ret = val.get<bool>() ? 1 : 0; good = true; }
301 } else if constexpr (std::is_floating_point_v<T>) {
302 if(val.is_number()) { ret = val.get<T>(); good = true; }
303 } else if constexpr (std::is_same_v<T, std::string>) {
304 if(val.is_string()) { ret = val.get<std::string>(); good = true; }
305 else if(!val.is_null()) { ret = val.dump(); good = true; }
306 }
307 } catch(...) {}
309 return ret;
310 }
311};
312
322 public:
325
332 static JsonArray parse(const String &str, Error *err = nullptr) {
334 try {
335 ret._j = nlohmann::json::parse(str.str());
336 if(!ret._j.is_array()) throw std::runtime_error("not an array");
337 if(err) *err = Error::Ok;
338 } catch(...) {
339 ret._j = nlohmann::json::array();
340 if(err) *err = Error::Invalid;
341 }
342 return ret;
343 }
344
347
349 int size() const { return static_cast<int>(_j.size()); }
350
352 bool isValid() const { return size() > 0; }
353
358 bool valueIsNull(int index) const { return index >= 0 && index < size() && _j[index].is_null(); }
359
364 bool valueIsObject(int index) const { return index >= 0 && index < size() && _j[index].is_object(); }
365
370 bool valueIsArray(int index) const { return index >= 0 && index < size() && _j[index].is_array(); }
371
378 bool getBool(int index, Error *err = nullptr) const { return get<bool>(index, err); }
379
386 int64_t getInt(int index, Error *err = nullptr) const { return get<int64_t>(index, err); }
387
394 uint64_t getUInt(int index, Error *err = nullptr) const { return get<uint64_t>(index, err); }
395
402 double getDouble(int index, Error *err = nullptr) const { return get<double>(index, err); }
403
410 String getString(int index, Error *err = nullptr) const { return get<std::string>(index, err); }
411
418 JsonObject getObject(int index, Error *err = nullptr) const {
419 if(index < 0 || index >= size() || !_j[index].is_object()) {
420 if(err) *err = Error::Invalid;
421 return JsonObject();
422 }
423 if(err) *err = Error::Ok;
425 ret._j = _j[index];
426 return ret;
427 }
428
435 JsonArray getArray(int index, Error *err = nullptr) const {
436 if(index < 0 || index >= size() || !_j[index].is_array()) {
437 if(err) *err = Error::Invalid;
438 return JsonArray();
439 }
440 if(err) *err = Error::Ok;
442 ret._j = _j[index];
443 return ret;
444 }
445
451 String toString(unsigned int indent = 0) const {
452 if(indent == 0) return _j.dump();
453 return _j.dump(static_cast<int>(indent));
454 }
455
457 void clear() { _j.clear(); }
458
460 void addNull() { _j.push_back(nullptr); }
462 void add(const JsonObject &val) { _j.push_back(val._j); }
464 void add(const JsonArray &val) { _j.push_back(val._j); }
466 void add(bool val) { _j.push_back(val); }
468 void add(int val) { _j.push_back(val); }
470 void add(unsigned int val) { _j.push_back(val); }
472 void add(int64_t val) { _j.push_back(val); }
474 void add(uint64_t val) { _j.push_back(val); }
476 void add(float val) { _j.push_back(val); }
478 void add(double val) { _j.push_back(val); }
480 void add(const char *val) { _j.push_back(std::string(val)); }
482 void add(const String &val) { _j.push_back(val.str()); }
484 void add(const UUID &val) { _j.push_back(val.toString().str()); }
485
491 switch(val.type()) {
492 case Variant::TypeInvalid: _j.push_back(nullptr); break;
493 case Variant::TypeBool: _j.push_back(val.get<bool>()); break;
494 case Variant::TypeU8: _j.push_back(val.get<uint8_t>()); break;
495 case Variant::TypeS8: _j.push_back(val.get<int8_t>()); break;
496 case Variant::TypeU16: _j.push_back(val.get<uint16_t>()); break;
497 case Variant::TypeS16: _j.push_back(val.get<int16_t>()); break;
498 case Variant::TypeU32: _j.push_back(val.get<uint32_t>()); break;
499 case Variant::TypeS32: _j.push_back(val.get<int32_t>()); break;
500 case Variant::TypeU64: _j.push_back(val.get<uint64_t>()); break;
501 case Variant::TypeS64: _j.push_back(val.get<int64_t>()); break;
502 case Variant::TypeFloat: _j.push_back(val.get<float>()); break;
503 case Variant::TypeDouble: _j.push_back(val.get<double>()); break;
504 default: _j.push_back(val.get<String>().str()); break;
505 }
506 }
507
513 template <typename Func> void forEach(Func &&func) const {
514 for(const auto &elem : _j) {
515 Variant val = Variant::fromJson(elem);
516 func(val);
517 }
518 }
519
520 private:
521 friend class JsonObject;
522
524
525 template <typename T>
526 T get(int index, Error *err = nullptr) const {
528 if(err) *err = Error::Invalid;
529 return T{};
530 }
531 return JsonObject::getVal<T>(_j[index], err);
532 }
533};
534
535// Inline definitions that depend on JsonArray being complete
536inline JsonArray JsonObject::getArray(const String &key, Error *err) const {
537 auto it = _j.find(key.str());
538 if(it == _j.end() || !it->is_array()) {
539 if(err) *err = Error::Invalid;
540 return JsonArray();
541 }
542 if(err) *err = Error::Ok;
544 ret._j = *it;
545 return ret;
546}
547
548inline void JsonObject::set(const String &key, const JsonArray &val) {
549 _j[key.str()] = val._j;
550}
551
Lightweight error code wrapper for the promeki library.
Definition error.h:39
@ Ok
No error.
Definition error.h:51
@ Invalid
Invalid value or argument (EINVAL).
Definition error.h:66
JSON array container wrapping nlohmann::json.
Definition json.h:320
bool valueIsNull(int index) const
Returns true if the element at the given index is null.
Definition json.h:358
void add(uint64_t val)
Appends an unsigned 64-bit integer to the array.
Definition json.h:474
void add(bool val)
Appends a boolean value to the array.
Definition json.h:466
JsonArray()
Constructs an empty JSON array.
Definition json.h:346
JsonArray getArray(int index, Error *err=nullptr) const
Returns the nested JsonArray at the given index.
Definition json.h:435
void add(unsigned int val)
Appends an unsigned int value to the array.
Definition json.h:470
void add(const char *val)
Appends a C-string value to the array.
Definition json.h:480
void add(const UUID &val)
Appends a UUID (stored as its string representation) to the array.
Definition json.h:484
void forEach(Func &&func) const
Iterates over all elements in the array.
Definition json.h:513
static JsonArray parse(const String &str, Error *err=nullptr)
Parses a JSON array from a string.
Definition json.h:332
bool isValid() const
Returns true if the array contains at least one element.
Definition json.h:352
JsonObject getObject(int index, Error *err=nullptr) const
Returns the nested JsonObject at the given index.
Definition json.h:418
bool valueIsObject(int index) const
Returns true if the element at the given index is a JSON object.
Definition json.h:364
String getString(int index, Error *err=nullptr) const
Returns the string value at the given index.
Definition json.h:410
int size() const
Returns the number of elements in the array.
Definition json.h:349
void add(float val)
Appends a float value to the array.
Definition json.h:476
void add(int val)
Appends an int value to the array.
Definition json.h:468
uint64_t getUInt(int index, Error *err=nullptr) const
Returns the unsigned 64-bit integer value at the given index.
Definition json.h:394
double getDouble(int index, Error *err=nullptr) const
Returns the double-precision floating-point value at the given index.
Definition json.h:402
void addFromVariant(const Variant &val)
Appends a value from a Variant, automatically selecting the JSON type.
Definition json.h:490
void add(const JsonObject &val)
Appends a JsonObject to the array.
Definition json.h:462
void addNull()
Appends a null value to the array.
Definition json.h:460
void clear()
Removes all elements from the array.
Definition json.h:457
void add(const JsonArray &val)
Appends a JsonArray to the array.
Definition json.h:464
String toString(unsigned int indent=0) const
Serializes the array to a JSON string.
Definition json.h:451
bool valueIsArray(int index) const
Returns true if the element at the given index is a JSON array.
Definition json.h:370
bool getBool(int index, Error *err=nullptr) const
Returns the boolean value at the given index.
Definition json.h:378
int64_t getInt(int index, Error *err=nullptr) const
Returns the signed 64-bit integer value at the given index.
Definition json.h:386
void add(double val)
Appends a double value to the array.
Definition json.h:478
void add(int64_t val)
Appends a signed 64-bit integer to the array.
Definition json.h:472
void add(const String &val)
Appends a String value to the array.
Definition json.h:482
JSON object container wrapping nlohmann::json.
Definition json.h:44
void set(const String &key, float val)
Sets a float value for the given key.
Definition json.h:225
void clear()
Removes all key-value pairs from the object.
Definition json.h:192
String getString(const String &key, Error *err=nullptr) const
Returns the string value for the given key.
Definition json.h:153
JsonArray getArray(const String &key, Error *err=nullptr) const
Returns the nested JsonArray for the given key.
Definition json.h:536
bool valueIsObject(const String &key) const
Returns true if the value for the given key is a JSON object.
Definition json.h:93
void setFromVariant(const String &key, const Variant &val)
Sets a value from a Variant, automatically selecting the JSON type.
Definition json.h:240
void set(const String &key, uint64_t val)
Sets an unsigned 64-bit integer value for the given key.
Definition json.h:223
uint64_t getUInt(const String &key, Error *err=nullptr) const
Returns the unsigned 64-bit integer value for the given key.
Definition json.h:137
void set(const String &key, bool val)
Sets a boolean value for the given key.
Definition json.h:215
bool valueIsNull(const String &key) const
Returns true if the value for the given key is null.
Definition json.h:83
bool valueIsArray(const String &key) const
Returns true if the value for the given key is a JSON array.
Definition json.h:103
void set(const String &key, double val)
Sets a double value for the given key.
Definition json.h:227
void set(const String &key, int64_t val)
Sets a signed 64-bit integer value for the given key.
Definition json.h:221
void set(const String &key, const JsonObject &val)
Sets a nested JsonObject value for the given key.
Definition json.h:205
void set(const String &key, const char *val)
Sets a C-string value for the given key.
Definition json.h:229
bool isValid() const
Returns true if the object contains at least one key-value pair.
Definition json.h:76
void forEach(Func &&func) const
Iterates over all key-value pairs in the object.
Definition json.h:264
bool operator==(const JsonObject &other) const
Returns true if both JSON objects have identical contents.
Definition json.h:273
JsonObject()
Constructs an empty JSON object.
Definition json.h:70
JsonObject getObject(const String &key, Error *err=nullptr) const
Returns the nested JsonObject for the given key.
Definition json.h:161
bool contains(const String &key) const
Returns true if the object contains the given key.
Definition json.h:113
int64_t getInt(const String &key, Error *err=nullptr) const
Returns the signed 64-bit integer value for the given key.
Definition json.h:129
void set(const String &key, unsigned int val)
Sets an unsigned int value for the given key.
Definition json.h:219
void set(const String &key, const String &val)
Sets a String value for the given key.
Definition json.h:231
void set(const String &key, const UUID &val)
Sets a UUID value (stored as its string representation) for the given key.
Definition json.h:233
bool getBool(const String &key, Error *err=nullptr) const
Returns the boolean value for the given key.
Definition json.h:121
void setNull(const String &key)
Sets the value for the given key to null.
Definition json.h:198
int size() const
Returns the number of key-value pairs in the object.
Definition json.h:73
String toString(unsigned int indent=0) const
Serializes the object to a JSON string.
Definition json.h:186
double getDouble(const String &key, Error *err=nullptr) const
Returns the double-precision floating-point value for the given key.
Definition json.h:145
static JsonObject parse(const String &str, Error *err=nullptr)
Parses a JSON object from a string.
Definition json.h:56
void set(const String &key, int val)
Sets an int value for the given key.
Definition json.h:217
Dynamic array container wrapping std::vector.
Definition list.h:40
List()=default
Default constructor. Creates an empty list.
void clear() noexcept
Removes all elements from the list.
Definition list.h:330
Iterator end() noexcept
Returns a mutable iterator to one past the last element.
Definition list.h:198
Encoding-aware string class with copy-on-write semantics.
Definition string.h:35
const std::string & str() const
Returns a const reference to the underlying std::string.
Definition string.h:286
Universally Unique Identifier (UUID).
Definition uuid.h:34
#define PROMEKI_NAMESPACE_BEGIN
Starts a promeki namespace block.
Definition namespace.h:14
#define PROMEKI_NAMESPACE_END
Ends a promeki namespace block.
Definition namespace.h:19
#define PROMEKI_SHARED_FINAL(TYPE)
Macro for non-polymorphic native shared objects.
Definition sharedptr.h:88