// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "languageserverprotocol_global.h" #include "lsputils.h" #include #include #include #include namespace LanguageServerProtocol { using Key = QLatin1StringView; class LANGUAGESERVERPROTOCOL_EXPORT JsonObject { public: using iterator = QJsonObject::iterator; using const_iterator = QJsonObject::const_iterator; JsonObject() = default; explicit JsonObject(const QJsonObject &object) : m_jsonObject(object) { } explicit JsonObject(QJsonObject &&object) : m_jsonObject(std::move(object)) { } JsonObject(const JsonObject &object) : m_jsonObject(object.m_jsonObject) { } JsonObject(JsonObject &&object) : m_jsonObject(std::move(object.m_jsonObject)) { } explicit JsonObject(const QJsonValue &value) : m_jsonObject(value.toObject()) { } virtual ~JsonObject() = default; JsonObject &operator=(const JsonObject &other); JsonObject &operator=(JsonObject &&other); bool operator==(const JsonObject &other) const { return m_jsonObject == other.m_jsonObject; } operator const QJsonObject&() const { return m_jsonObject; } virtual bool isValid() const { return true; } iterator end() { return m_jsonObject.end(); } const_iterator end() const { return m_jsonObject.end(); } protected: iterator insert(const Key key, const JsonObject &value); iterator insert(const Key key, const QJsonValue &value); template iterator insertVariant(const Key key, const V &variant); template iterator insertVariant(const Key key, const V &variant); // QJSonObject redirections QJsonValue value(const QString &key) const { return m_jsonObject.value(key); } QJsonValue value(const Key key) const { return m_jsonObject.value(key); } bool contains(const Key key) const { return m_jsonObject.contains(key); } iterator find(const Key key) { return m_jsonObject.find(key); } const_iterator find(const Key key) const { return m_jsonObject.find(key); } void remove(const Key key) { m_jsonObject.remove(key); } QStringList keys() const { return m_jsonObject.keys(); } // convenience value access template T typedValue(const Key key) const; template std::optional optionalValue(const Key key) const; template LanguageClientValue clientValue(const Key key) const; template std::optional> optionalClientValue(const Key key) const; template QList array(const Key key) const; template std::optional> optionalArray(const Key key) const; template LanguageClientArray clientArray(const Key key) const; template std::optional> optionalClientArray(const Key key) const; template void insertArray(const Key key, const QList &array); template void insertArray(const Key key, const QList &array); private: QJsonObject m_jsonObject; }; template JsonObject::iterator JsonObject::insertVariant(const Key key, const V &variant) { const auto v = std::get_if(&variant); return v ? insert(key, *v) : end(); } template JsonObject::iterator JsonObject::insertVariant(const Key key, const V &variant) { auto result = insertVariant(key, variant); return result != end() ? result : insertVariant(key, variant); } template T JsonObject::typedValue(const Key key) const { return fromJsonValue(value(key)); } template std::optional JsonObject::optionalValue(const Key key) const { const QJsonValue &val = value(key); return val.isUndefined() ? std::nullopt : std::make_optional(fromJsonValue(val)); } template LanguageClientValue JsonObject::clientValue(const Key key) const { return LanguageClientValue(value(key)); } template std::optional> JsonObject::optionalClientValue(const Key key) const { return contains(key) ? std::make_optional(clientValue(key)) : std::nullopt; } template QList JsonObject::array(const Key key) const { if (const std::optional> &array = optionalArray(key)) return *array; qCDebug(conversionLog) << QString("Expected array under %1 in:").arg(key) << *this; return {}; } template std::optional> JsonObject::optionalArray(const Key key) const { const QJsonValue &jsonValue = value(key); if (jsonValue.isUndefined()) return std::nullopt; return Utils::transform>(jsonValue.toArray(), &fromJsonValue); } template LanguageClientArray JsonObject::clientArray(const Key key) const { return LanguageClientArray(value(key)); } template std::optional> JsonObject::optionalClientArray(const Key key) const { const QJsonValue &val = value(key); return !val.isUndefined() ? std::make_optional(LanguageClientArray(value(key))) : std::nullopt; } template void JsonObject::insertArray(const Key key, const QList &array) { QJsonArray jsonArray; for (const T &item : array) jsonArray.append(QJsonValue(item)); insert(key, jsonArray); } template void JsonObject::insertArray(const Key key, const QList &array) { QJsonArray jsonArray; for (const JsonObject &item : array) jsonArray.append(item.m_jsonObject); insert(key, jsonArray); } } // namespace LanguageServerProtocol