cesium-native 0.44.2
Loading...
Searching...
No Matches
JsonValue.h
1#pragma once
2
3#include <CesiumUtility/Library.h>
4
5#include <cmath>
6#include <cstdint>
7#include <initializer_list>
8#include <map>
9#include <optional>
10#include <stdexcept>
11#include <string>
12#include <string_view>
13#include <type_traits>
14#include <variant>
15#include <vector>
16
17namespace CesiumUtility {
18
28template <typename TTo, typename TFrom>
29extern std::optional<TTo> losslessNarrow(TFrom from) noexcept;
30
42template <typename TTo, typename TFrom>
43constexpr TTo losslessNarrowOrDefault(TFrom from, TTo defaultValue) noexcept {
44 return losslessNarrow<TTo, TFrom>(from).value_or(defaultValue);
45}
46
53class CESIUMUTILITY_API JsonValue final {
54public:
58 using Null = std::nullptr_t;
59
63 using Bool = bool;
64
68 using String = std::string;
69
73 using Object = std::map<std::string, JsonValue>;
74
78 using Array = std::vector<JsonValue>;
79
83 JsonValue() noexcept : value() {}
84
88 JsonValue(std::nullptr_t) noexcept : value(nullptr) {}
89
95 JsonValue(double v) noexcept {
96 if (std::isnan(v) || std::isinf(v)) {
97 value = nullptr;
98 } else {
99 value = v;
100 }
101 }
102
107 JsonValue(std::int8_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
108
113 JsonValue(std::uint8_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
114
119 JsonValue(std::int16_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
120
125 JsonValue(std::uint16_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
126
131 JsonValue(std::int32_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
132
137 JsonValue(std::uint32_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
138
142 JsonValue(std::int64_t v) noexcept : value(v) {}
143
147 JsonValue(std::uint64_t v) noexcept : value(v) {}
148
152 JsonValue(bool v) noexcept : value(v) {}
153
157 JsonValue(const std::string& v) : value(v) {}
158
162 JsonValue(std::string&& v) noexcept : value(std::move(v)) {}
163
167 JsonValue(const char* v) : value(std::string(v)) {}
168
172 JsonValue(const std::map<std::string, JsonValue>& v) : value(v) {}
173
177 JsonValue(std::map<std::string, JsonValue>&& v) : value(std::move(v)) {}
178
182 JsonValue(const std::vector<JsonValue>& v) : value(v) {}
183
187 JsonValue(std::vector<JsonValue>&& v) noexcept : value(std::move(v)) {}
188
192 JsonValue(std::initializer_list<JsonValue> v)
193 : value(std::vector<JsonValue>(v)) {}
194
198 JsonValue(std::initializer_list<std::pair<const std::string, JsonValue>> v)
199 : value(std::map<std::string, JsonValue>(v)) {}
200
209 [[nodiscard]] const JsonValue*
210 getValuePtrForKey(const std::string& key) const;
212 [[nodiscard]] JsonValue* getValuePtrForKey(const std::string& key);
213
228 template <typename T>
229 const T* getValuePtrForKey(const std::string& key) const {
230 const JsonValue* pValue = this->getValuePtrForKey(key);
231 if (!pValue) {
232 return nullptr;
233 }
234
235 return std::get_if<T>(&pValue->value);
236 }
237
252 template <typename T> T* getValuePtrForKey(const std::string& key) {
253 JsonValue* pValue = this->getValuePtrForKey(key);
254 return std::get_if<T>(&pValue->value);
255 }
256
272 template <
273 typename To,
274 typename std::enable_if<
275 std::is_integral<To>::value ||
276 std::is_floating_point<To>::value>::type* = nullptr>
277 [[nodiscard]] std::optional<To>
278 getSafeNumericalValueForKey(const std::string& key) const {
279 const Object& pObject = std::get<Object>(this->value);
280 const auto it = pObject.find(key);
281 if (it == pObject.end()) {
282 return std::nullopt;
283 }
284 return it->second.getSafeNumber<To>();
285 }
286
306 template <
307 typename To,
308 typename std::enable_if<
309 std::is_integral<To>::value ||
310 std::is_floating_point<To>::value>::type* = nullptr>
312 const std::string& key,
313 To defaultValue) const {
314 const Object& pObject = std::get<Object>(this->value);
315 const auto it = pObject.find(key);
316 if (it == pObject.end()) {
317 return defaultValue;
318 }
319 return it->second.getSafeNumberOrDefault<To>(defaultValue);
320 }
321
329 [[nodiscard]] inline bool hasKey(const std::string& key) const {
330 const Object* pObject = std::get_if<Object>(&this->value);
331 if (!pObject) {
332 return false;
333 }
334
335 return pObject->find(key) != pObject->end();
336 }
337
346 template <
347 typename To,
348 typename std::enable_if<
349 std::is_integral<To>::value ||
350 std::is_floating_point<To>::value>::type* = nullptr>
351 [[nodiscard]] std::optional<To> getSafeNumber() const {
352 const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
353 if (uInt) {
354 return losslessNarrow<To>(*uInt);
355 }
356
357 const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
358 if (sInt) {
359 return losslessNarrow<To>(*sInt);
360 }
361
362 const double* real = std::get_if<double>(&this->value);
363 if (real) {
364 return losslessNarrow<To>(*real);
365 }
366
367 return std::nullopt;
368 }
369
377 template <
378 typename To,
379 typename std::enable_if<
380 std::is_integral<To>::value ||
381 std::is_floating_point<To>::value>::type* = nullptr>
382 [[nodiscard]] To getSafeNumberOrDefault(To defaultValue) const noexcept {
383 const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
384 if (uInt) {
385 return losslessNarrowOrDefault<To>(*uInt, defaultValue);
386 }
387
388 const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
389 if (sInt) {
390 return losslessNarrowOrDefault<To>(*sInt, defaultValue);
391 }
392
393 const double* real = std::get_if<double>(&this->value);
394 if (real) {
395 return losslessNarrowOrDefault<To>(*real, defaultValue);
396 }
397
398 return defaultValue;
399 }
400
408 [[nodiscard]] inline const JsonValue::Object& getObject() const {
409 return std::get<JsonValue::Object>(this->value);
410 }
411
418 [[nodiscard]] inline const JsonValue::String& getString() const {
419 return std::get<String>(this->value);
420 }
421
428 [[nodiscard]] inline const JsonValue::Array& getArray() const {
429 return std::get<JsonValue::Array>(this->value);
430 }
431
440 [[nodiscard]] std::vector<std::string>
441 getArrayOfStrings(const std::string& defaultString) const;
442
449 [[nodiscard]] inline bool getBool() const {
450 return std::get<bool>(this->value);
451 }
452
458 [[nodiscard]] inline double getDouble() const {
459 return std::get<double>(this->value);
460 }
461
468 [[nodiscard]] std::uint64_t getUint64() const {
469 return std::get<std::uint64_t>(this->value);
470 }
471
478 [[nodiscard]] std::int64_t getInt64() const {
479 return std::get<std::int64_t>(this->value);
480 }
481
486 [[nodiscard]] inline bool getBoolOrDefault(bool defaultValue) const noexcept {
487 const auto* v = std::get_if<bool>(&this->value);
488 if (v) {
489 return *v;
490 }
491
492 return defaultValue;
493 }
494
499 [[nodiscard]] inline const JsonValue::String
500 getStringOrDefault(String defaultValue) const {
501 const auto* v = std::get_if<JsonValue::String>(&this->value);
502 if (v) {
503 return *v;
504 }
505
506 return defaultValue;
507 }
508
513 [[nodiscard]] inline double
514 getDoubleOrDefault(double defaultValue) const noexcept {
515 const auto* v = std::get_if<double>(&this->value);
516 if (v) {
517 return *v;
518 }
519
520 return defaultValue;
521 }
522
527 [[nodiscard]] inline std::uint64_t
528 getUint64OrDefault(std::uint64_t defaultValue) const noexcept {
529 const auto* v = std::get_if<std::uint64_t>(&this->value);
530 if (v) {
531 return *v;
532 }
533
534 return defaultValue;
535 }
536
541 [[nodiscard]] inline std::int64_t
542 getInt64OrDefault(std::int64_t defaultValue) const noexcept {
543 const auto* v = std::get_if<std::int64_t>(&this->value);
544 if (v) {
545 return *v;
546 }
547
548 return defaultValue;
549 }
550
554 [[nodiscard]] inline bool isNull() const noexcept {
555 return std::holds_alternative<Null>(this->value);
556 }
557
563 [[nodiscard]] inline bool isNumber() const noexcept {
564 return isDouble() || isUint64() || isInt64();
565 }
566
570 [[nodiscard]] inline bool isBool() const noexcept {
571 return std::holds_alternative<Bool>(this->value);
572 }
573
577 [[nodiscard]] inline bool isString() const noexcept {
578 return std::holds_alternative<String>(this->value);
579 }
580
584 [[nodiscard]] inline bool isObject() const noexcept {
585 return std::holds_alternative<Object>(this->value);
586 }
587
591 [[nodiscard]] inline bool isArray() const noexcept {
592 return std::holds_alternative<Array>(this->value);
593 }
594
598 [[nodiscard]] inline bool isDouble() const noexcept {
599 return std::holds_alternative<double>(this->value);
600 }
601
605 [[nodiscard]] inline bool isUint64() const noexcept {
606 return std::holds_alternative<std::uint64_t>(this->value);
607 }
608
612 [[nodiscard]] inline bool isInt64() const noexcept {
613 return std::holds_alternative<std::int64_t>(this->value);
614 }
615
619 inline bool operator==(const JsonValue& rhs) const noexcept {
620 return this->value == rhs.value;
621 };
622
626 int64_t getSizeBytes() const noexcept {
627 struct Operation {
628 int64_t operator()([[maybe_unused]] const Null& /*inside*/) { return 0; }
629 int64_t operator()([[maybe_unused]] const double& /*inside*/) {
630 return 0;
631 }
632 int64_t operator()([[maybe_unused]] const std::uint64_t& /*inside*/) {
633 return 0;
634 }
635 int64_t operator()([[maybe_unused]] const std::int64_t& /*inside*/) {
636 return 0;
637 }
638 int64_t operator()([[maybe_unused]] const Bool& /*inside*/) { return 0; }
639 int64_t operator()(const String& inside) {
640 return int64_t(inside.capacity() * sizeof(char));
641 }
642 int64_t operator()(const Object& inside) {
643 int64_t accum = 0;
644 accum +=
645 int64_t(inside.size() * (sizeof(std::string) + sizeof(JsonValue)));
646 for (const auto& [k, v] : inside) {
647 accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
648 accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
649 }
650
651 return accum;
652 }
653 int64_t operator()(const Array& inside) {
654 int64_t accum = 0;
655 accum += int64_t(sizeof(JsonValue) * inside.capacity());
656 for (const JsonValue& v : inside) {
657 accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
658 }
659 return accum;
660 }
661 };
662
663 return static_cast<int64_t>(sizeof(JsonValue)) +
664 std::visit(Operation{}, this->value);
665 }
666
679 std::variant<
680 Null,
681 double,
682 std::uint64_t,
683 std::int64_t,
684 Bool,
685 String,
686 Object,
687 Array>
689};
690} // namespace CesiumUtility
A generic implementation of a value in a JSON structure.
Definition JsonValue.h:53
std::vector< std::string > getArrayOfStrings(const std::string &defaultString) const
Gets an array of strings from the value.
std::map< std::string, JsonValue > Object
The type to represent an Object JSON value.
Definition JsonValue.h:73
JsonValue(std::int8_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int8_t).
Definition JsonValue.h:107
std::optional< To > getSafeNumericalValueForKey(const std::string &key) const
Converts the numerical value corresponding to the given key to the provided numerical template type.
Definition JsonValue.h:278
bool getBool() const
Gets the bool from the value.
Definition JsonValue.h:449
JsonValue(const std::map< std::string, JsonValue > &v)
Creates an Object JSON value with the given properties.
Definition JsonValue.h:172
bool isInt64() const noexcept
Returns whether this value is a std::int64_t value.
Definition JsonValue.h:612
const JsonValue::String & getString() const
Gets the string from the value.
Definition JsonValue.h:418
JsonValue(std::int16_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int16_t).
Definition JsonValue.h:119
bool isNumber() const noexcept
Returns whether this value is a double, std::uint64_t or std::int64_t. Use this function in conjuncti...
Definition JsonValue.h:563
bool isDouble() const noexcept
Returns whether this value is a double value.
Definition JsonValue.h:598
JsonValue(std::vector< JsonValue > &&v) noexcept
Creates an Array JSON value with the given elements.
Definition JsonValue.h:187
std::vector< JsonValue > Array
The type to represent an Array JSON value.
Definition JsonValue.h:78
double getDoubleOrDefault(double defaultValue) const noexcept
Gets the double from the value or returns defaultValue.
Definition JsonValue.h:514
JsonValue * getValuePtrForKey(const std::string &key)
Attempts to obtain a pointer to a JsonValue for the given key on this object.
JsonValue(std::initializer_list< JsonValue > v)
Creates an JSON value from the given initializer list.
Definition JsonValue.h:192
JsonValue(std::uint16_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint16_t).
Definition JsonValue.h:125
std::variant< Null, double, std::uint64_t, std::int64_t, Bool, String, Object, Array > value
The actual value.
Definition JsonValue.h:688
bool isBool() const noexcept
Returns whether this value is a Bool value.
Definition JsonValue.h:570
const JsonValue::String getStringOrDefault(String defaultValue) const
Gets the string from the value or returns defaultValue.
Definition JsonValue.h:500
JsonValue(std::nullptr_t) noexcept
Creates a null JSON value.
Definition JsonValue.h:88
JsonValue(std::string &&v) noexcept
Creates a String JSON value.
Definition JsonValue.h:162
bool Bool
The type to represent a Bool JSON value.
Definition JsonValue.h:63
JsonValue(bool v) noexcept
Creates a Bool JSON value.
Definition JsonValue.h:152
bool isNull() const noexcept
Returns whether this value is a null value.
Definition JsonValue.h:554
const T * getValuePtrForKey(const std::string &key) const
Gets a typed value corresponding to the given key in the object represented by this instance.
Definition JsonValue.h:229
std::uint64_t getUint64() const
Gets the std::uint64_t from the value.
Definition JsonValue.h:468
bool operator==(const JsonValue &rhs) const noexcept
Returns true if two values are equal.
Definition JsonValue.h:619
std::int64_t getInt64OrDefault(std::int64_t defaultValue) const noexcept
Gets the int64_t from the value or returns defaultValue.
Definition JsonValue.h:542
std::string String
The type to represent a String JSON value.
Definition JsonValue.h:68
JsonValue(const char *v)
Creates a String JSON value.
Definition JsonValue.h:167
bool isUint64() const noexcept
Returns whether this value is a std::uint64_t value.
Definition JsonValue.h:605
T * getValuePtrForKey(const std::string &key)
Gets a typed value corresponding to the given key in the object represented by this instance.
Definition JsonValue.h:252
JsonValue(std::int64_t v) noexcept
Creates a std::int64_t JSON value.
Definition JsonValue.h:142
bool isArray() const noexcept
Returns whether this value is an Array value.
Definition JsonValue.h:591
JsonValue() noexcept
Default constructor.
Definition JsonValue.h:83
bool isString() const noexcept
Returns whether this value is a String value.
Definition JsonValue.h:577
bool isObject() const noexcept
Returns whether this value is an Object value.
Definition JsonValue.h:584
JsonValue(double v) noexcept
Creates a Number JSON value.
Definition JsonValue.h:95
std::int64_t getInt64() const
Gets the std::int64_t from the value.
Definition JsonValue.h:478
JsonValue(std::map< std::string, JsonValue > &&v)
Creates an Object JSON value with the given properties.
Definition JsonValue.h:177
bool getBoolOrDefault(bool defaultValue) const noexcept
Gets the bool from the value or returns defaultValue.
Definition JsonValue.h:486
To getSafeNumberOrDefault(To defaultValue) const noexcept
Gets the numerical quantity from the value casted to the To type or returns defaultValue if unable to...
Definition JsonValue.h:382
double getDouble() const
Gets the double from the value.
Definition JsonValue.h:458
JsonValue(const std::string &v)
Creates a String JSON value.
Definition JsonValue.h:157
JsonValue(std::uint32_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint32_t).
Definition JsonValue.h:137
const JsonValue::Object & getObject() const
Gets the object from the value.
Definition JsonValue.h:408
const JsonValue * getValuePtrForKey(const std::string &key) const
Attempts to obtain a pointer to a JsonValue for the given key on this object.
std::uint64_t getUint64OrDefault(std::uint64_t defaultValue) const noexcept
Gets the uint64_t from the value or returns defaultValue.
Definition JsonValue.h:528
JsonValue(std::uint8_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint8_t).
Definition JsonValue.h:113
int64_t getSizeBytes() const noexcept
Returns the size in bytes of this JsonValue.
Definition JsonValue.h:626
JsonValue(std::int32_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int32_t).
Definition JsonValue.h:131
JsonValue(std::uint64_t v) noexcept
Creates a std::uint64_t JSON value.
Definition JsonValue.h:147
std::optional< To > getSafeNumber() const
Gets the numerical quantity from the value casted to the To type. This function should be used over g...
Definition JsonValue.h:351
To getSafeNumericalValueOrDefaultForKey(const std::string &key, To defaultValue) const
Converts the numerical value corresponding to the given key to the provided numerical template type.
Definition JsonValue.h:311
const JsonValue::Array & getArray() const
Gets the array from the value.
Definition JsonValue.h:428
JsonValue(const std::vector< JsonValue > &v)
Creates an Array JSON value with the given elements.
Definition JsonValue.h:182
JsonValue(std::initializer_list< std::pair< const std::string, JsonValue > > v)
Creates an JSON value from the given initializer list.
Definition JsonValue.h:198
std::nullptr_t Null
The type to represent a null JSON value.
Definition JsonValue.h:58
bool hasKey(const std::string &key) const
Determines if this value is an Object and has the given key.
Definition JsonValue.h:329
Utility classes for Cesium.
constexpr TTo losslessNarrowOrDefault(TFrom from, TTo defaultValue) noexcept
Attempts a narrowing conversion of TFrom into TTo without losing information. If a lossless conversio...
Definition JsonValue.h:43
std::optional< TTo > losslessNarrow(TFrom from) noexcept
Attempts a narrowing conversion of TFrom into TTo without losing information. If a lossless conversio...
STL namespace.