AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AJson.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12#pragma once
   13
   14#include <AUI/IO/IOutputStream.h>
   15#include "AUI/Common/AException.h"
   16#include "AUI/Common/AOptional.h"
   17#include "AUI/Common/SharedPtr.h"
   18#include "AUI/IO/IInputStream.h"
   19#include "AJson.h"
   20#include "AUI/Common/AByteBufferView.h"
   21
   22#include <AUI/Common/AUuid.h>
   23#include <AUI/Common/AMap.h>
   24#include <AUI/Json/AJson.h>
   25#include <AUI/Json/Exception.h>
   26#include <AUI/Traits/callables.h>
   27#include <variant>
   28
   33
   34class AJson;
   35namespace aui::impl {
   36    struct JsonObject: AVector<std::pair<AString, AJson>> {
   37    public:
   38        using AVector<std::pair<AString, AJson>>::AVector;
   39
   43        [[nodiscard]]
   44        API_AUI_JSON std::pair<AString, AJson>* contains(const AString& key) noexcept;
   45
   49        [[nodiscard]]
   50        const std::pair<AString, AJson>* contains(const AString& key) const noexcept {
   51            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
   52            return const_cast<JsonObject&>(*this).contains(key);
   53        }
   54
   55        [[nodiscard]] API_AUI_JSON AJson& operator[](const AString& key);
   56
   57        [[nodiscard]] const AJson& operator[](const AString& key) const {
   58            return at(key);
   59        }
   60
   65        [[nodiscard]] API_AUI_JSON AJson& at(const AString& key);
   66
   71        [[nodiscard]] const AJson& at(const AString& key) const {
   72            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
   73            return const_cast<JsonObject&>(*this).at(key);
   74        }
   75    };
   76    using JsonArray = AVector<AJson>;
   77    using JsonVariant = std::variant<std::nullopt_t, std::nullptr_t, int, int64_t, double, bool, AString, aui::impl::JsonArray, aui::impl::JsonObject>;
   78}
   79
   84class AJson: public aui::impl::JsonVariant {
   85private:
   86    using super = aui::impl::JsonVariant;
   87
   88    template<typename T>
   89    [[nodiscard]]
   90    bool is() const noexcept {
   91        return std::holds_alternative<T>(*this);
   92    }
   93    template<typename T>
   94    [[nodiscard]]
   95    T& as() {
   96        if (isEmpty()) {
   97            *this = T();
   98        }
   99
  100        if (auto p = std::get_if<T>(this)) {
  101            return *p;
  102        }
  103        throw AJsonTypeMismatchException("not a " + AClass<T>::name());
  104    }
  105
  106    template<typename T>
  107    [[nodiscard]]
  108    const T& as() const {
  109        if (auto p = std::get_if<T>(this)) {
  110            return *p;
  111        }
  112        if constexpr(std::is_same_v<T, aui::impl::JsonObject>) {
  113            throw AJsonTypeMismatchException("not an object");
  114        } else if constexpr(std::is_same_v<T, aui::impl::JsonArray>) {
  115            throw AJsonTypeMismatchException("not an array");
  116        } else {
  117            throw AJsonTypeMismatchException("not a " + AClass<T>::name());
  118        }
  119    }
  120public:
  121    using aui::impl::JsonVariant::variant;
  122
  123    using Array = aui::impl::JsonArray;
  124    using Object = aui::impl::JsonObject;
  125
  126    AJson(std::initializer_list<std::pair<AString, AJson>> elems): aui::impl::JsonVariant(aui::impl::JsonObject(std::move(elems))) {
  127
  128    }
  129
  130    AJson(const char* name): aui::impl::JsonVariant(AString(name)) {}
  131    AJson(const AJson& json) = default;
  132    AJson(AJson&&) noexcept = default;
  133    AJson& operator=(const AJson&) = default;
  134    AJson& operator=(AJson&&) noexcept = default;
  135
  136    AJson() noexcept: aui::impl::JsonVariant(std::nullopt) {}
  137
  138    [[nodiscard]]
  139    bool isInt() const noexcept {
  140        return is<int>();
  141    }
  142
  143    [[nodiscard]]
  144    bool isLongInt() const noexcept {
  145        return isInt() || is<int64_t>();
  146    }
  147
  148    [[nodiscard]]
  149    bool isEmpty() const noexcept {
  150        return is<std::nullopt_t>();
  151    }
  152
  153    [[nodiscard]]
  154    bool isNumber() const noexcept {
  155        return isInt() || is<double>();
  156    }
  157
  158    [[nodiscard]]
  159    bool isBool() const noexcept {
  160        return is<bool>();
  161    }
  162
  163    [[nodiscard]]
  164    bool isNull() const noexcept {
  165        return is<std::nullptr_t>();
  166    }
  167
  168    [[nodiscard]]
  169    bool isString() const noexcept {
  170        return is<AString>();
  171    }
  172
  173    [[nodiscard]]
  174    bool isArray() const noexcept {
  175        return is<aui::impl::JsonArray>();
  176    }
  177
  178    [[nodiscard]]
  179    bool isObject() const noexcept {
  180        return is<aui::impl::JsonObject>();
  181    }
  182
  183    [[nodiscard]]
  184    int asInt() const {
  185        return as<int>();
  186    }
  187
  188    [[nodiscard]]
  189    int64_t asLongInt() const {
  190        return std::visit(aui::lambda_overloaded{
  191            [](auto&& e) -> std::int64_t {
  192                throw AJsonTypeMismatchException("not a long int");
  193            },
  194            [](std::int64_t v) -> std::int64_t {
  195                return v;
  196            },
  197            [](int v) -> std::int64_t {
  198                return v;
  199            },
  200        }, (super)const_cast<AJson&>(*this));
  201    }
  202
  203    [[nodiscard]]
  204    double asNumber() const {
  205        return std::visit(aui::lambda_overloaded{
  206                [](auto&& e) -> double {
  207                    throw AJsonTypeMismatchException("not a number");
  208                },
  209                [](double v) -> double {
  210                    return v;
  211                },
  212                [](int v) -> double {
  213                    return v;
  214                },
  215                [](int64_t v) -> double {
  216                    return v;
  217                },
  218        }, (super)const_cast<AJson&>(*this));
  219    }
  220
  221    [[nodiscard]]
  222    bool asBool() const {
  223        return as<bool>();
  224    }
  225
  226    [[nodiscard]]
  227    const AString& asString() const {
  228        return as<AString>();
  229    }
  230
  231    [[nodiscard]]
  232    const aui::impl::JsonArray& asArray() const {
  233        return as<aui::impl::JsonArray>();
  234    }
  235
  236    [[nodiscard]]
  237    const aui::impl::JsonObject& asObject() const {
  238        return as<aui::impl::JsonObject>();
  239    }
  240
  241
  242    [[nodiscard]]
  243    aui::impl::JsonArray& asArray() {
  244        return as<aui::impl::JsonArray>();
  245    }
  246
  247    [[nodiscard]]
  248    aui::impl::JsonObject& asObject() {
  249        return as<Object>();
  250    }
  251
  252    [[nodiscard]]
  253    bool contains(const AString& mapKey) const {
  254        return as<Object>().contains(mapKey);
  255    }
  256
  257    [[nodiscard]]
  258    AOptional<AJson> containsOpt(const AString& mapKey) const {
  259        if (auto c = as<Object>().contains(mapKey)) {
  260            return c->second;
  261        }
  262        return std::nullopt;
  263    }
  264
  265    AJson& operator[](const AString& mapKey) {
  266        return asObject()[mapKey];
  267    }
  268
  269    const AJson& operator[](const AString& mapKey) const {
  270        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
  271        return const_cast<AJson&>(*this)[mapKey];
  272    }
  273
  274
  275    AJson& operator[](int arrayIndex) {
  276        return as<Array>().at(arrayIndex);
  277    }
  278
  279    const AJson& operator[](int arrayIndex) const {
  280        return const_cast<AJson&>(*this)[arrayIndex];
  281    }
  282
  283    void push_back(AJson elem) {
  284        asArray().push_back(std::move(elem));
  285    }
  286
  287
  314    API_AUI_JSON AJson mergedWith(const AJson& other);
  315
  316    [[nodiscard]] static API_AUI_JSON AString toString(const AJson& json);
  317    [[nodiscard]] static API_AUI_JSON AJson fromString(const AString& json);
  318    [[nodiscard]] static AJson fromStream(aui::no_escape<IInputStream> stream) {
  319        return aui::deserialize<AJson>(stream);
  320    }
  321    [[nodiscard]] static API_AUI_JSON AJson fromBuffer(AByteBufferView buffer);
  322};
  323
  324
  325#include <AUI/Json/Conversion.h>
  326#include <AUI/Json/Serialization.h>
Acts like std::string_view but for AByteBuffer.
Definition AByteBufferView.h:24
static AString name()
[ARROW_ERROR_MESSAGE_EXAMPLE]
Definition AClass.h:28
Definition Exception.h:33
Json atom.
Definition AJson.h:84
API_AUI_JSON AJson mergedWith(const AJson &other)
Merges other json object into this object.
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition AOptional.h:33
Represents a Unicode character string.
Definition AString.h:38
A std::vector with AUI extensions.
Definition AVector.h:39
Definition AJson.h:36
const AJson & at(const AString &key) const
If container contains key, returns reference to the element.
Definition AJson.h:71
const std::pair< AString, AJson > * contains(const AString &key) const noexcept
If container contains key, returns pointer to the element. nullptr otherwise.
Definition AJson.h:50
API_AUI_JSON AJson & at(const AString &key)
If container contains key, returns reference to the element.
API_AUI_JSON std::pair< AString, AJson > * contains(const AString &key) noexcept
If container contains key, returns pointer to the element. nullptr otherwise.
Definition callables.h:36
Does not allow escaping, allowing to accept lvalue ref, rvalue ref, shared_ptr and etc without overhe...
Definition values.h:128