diff --git a/src/blackmisc/variant.cpp b/src/blackmisc/variant.cpp index a5a2f9dc2..7d0ab72ca 100644 --- a/src/blackmisc/variant.cpp +++ b/src/blackmisc/variant.cpp @@ -205,6 +205,48 @@ namespace BlackMisc } } + QJsonObject CVariant::toMemoizedJson() const + { + auto *meta = getValueObjectMetaInfo(); + if (meta) + { + try + { + QJsonObject json; + json.insert("type", this->typeName()); + json.insert("value", meta->toMemoizedJson(data())); + return json; + } + catch (const Private::CVariantException &ex) + { + CLogMessage(this).debug() << ex.what(); + return {}; + } + } + else + { + return toJson(); + } + } + + void CVariant::convertFromMemoizedJson(const QJsonObject &json) + { + QString typeName = json.value("type").toString(); + if (typeName.isEmpty()) { m_v.clear(); return; } + int typeId = QMetaType::type(qPrintable(typeName)); + + auto *meta = Private::getValueObjectMetaInfo(typeId); + if (meta) + { + m_v = QVariant(typeId, nullptr); + meta->convertFromMemoizedJson(json.value("value").toObject(), data()); + } + else + { + convertFromJson(json); + } + } + uint CVariant::getValueHash() const { switch (m_v.type()) diff --git a/src/blackmisc/variant.h b/src/blackmisc/variant.h index 637c3abec..857559cdb 100644 --- a/src/blackmisc/variant.h +++ b/src/blackmisc/variant.h @@ -277,6 +277,12 @@ namespace BlackMisc //! \copydoc BlackMisc::Mixin::JsonByMetaClass::convertFromJson void convertFromJson(const QJsonObject &json); + //! To compact JSON format. + QJsonObject toMemoizedJson() const; + + //! From compact JSON format. + void convertFromMemoizedJson(const QJsonObject &json); + //! \copydoc BlackMisc::Mixin::DBusByMetaClass::marshallToDbus void marshallToDbus(QDBusArgument &argument) const; diff --git a/src/blackmisc/variantmap.cpp b/src/blackmisc/variantmap.cpp index 8915e9dd3..652d57ef8 100644 --- a/src/blackmisc/variantmap.cpp +++ b/src/blackmisc/variantmap.cpp @@ -54,4 +54,44 @@ namespace BlackMisc } } + QJsonObject &CVariantMap::mergeToMemoizedJson(QJsonObject &json) const + { + for (auto it = cbegin(); it != cend(); ++it) + { + json.insert(it.key(), it.value().toMemoizedJson()); + } + return json; + } + + QJsonObject CVariantMap::toMemoizedJson() const + { + QJsonObject json; + mergeToMemoizedJson(json); + return json; + } + + void CVariantMap::convertFromMemoizedJson(const QJsonObject &json) + { + clear(); + for (auto it = json.begin(); it != json.end(); ++it) + { + CVariant value; + value.convertFromMemoizedJson(it.value().toObject()); + implementationOf(*this).insert(cend(), it.key(), value); + } + } + + void CVariantMap::convertFromMemoizedJson(const QJsonObject &json, const QStringList &keys) + { + clear(); + for (const auto &key : keys) + { + auto value = json.value(key); + if (value.isUndefined()) { continue; } + CVariant var; + var.convertFromMemoizedJson(value.toObject()); + insert(key, var); + } + } + } diff --git a/src/blackmisc/variantmap.h b/src/blackmisc/variantmap.h index 09a2aa118..fb4f07c81 100644 --- a/src/blackmisc/variantmap.h +++ b/src/blackmisc/variantmap.h @@ -68,6 +68,19 @@ namespace BlackMisc //! \copydoc BlackMisc::CValueObject::convertFromJson //! Convert only keys present in list argument. void convertFromJson(const QJsonObject &json, const QStringList &keys); + + //! Insert values from this map into an existing compact JSON object. + QJsonObject &mergeToMemoizedJson(QJsonObject &json) const; + + //! To compact JSON format. + QJsonObject toMemoizedJson() const; + + //! From compact JSON format. + void convertFromMemoizedJson(const QJsonObject &json); + + //! From compact JSON format. + //! Convert only keys present in list argument. + void convertFromMemoizedJson(const QJsonObject &json, const QStringList &keys); }; } diff --git a/src/blackmisc/variantprivate.h b/src/blackmisc/variantprivate.h index f8709ff0a..88ed7eb83 100644 --- a/src/blackmisc/variantprivate.h +++ b/src/blackmisc/variantprivate.h @@ -46,6 +46,8 @@ namespace BlackMisc virtual QString toQString(const void *object, bool i18n) const = 0; virtual QJsonObject toJson(const void *object) const = 0; virtual void convertFromJson(const QJsonObject &json, void *object) const = 0; + virtual QJsonObject toMemoizedJson(const void *object) const = 0; + virtual void convertFromMemoizedJson(const QJsonObject &json, void *object) const = 0; virtual void unmarshall(const QDBusArgument &arg, void *object) const = 0; virtual uint getValueHash(const void *object) const = 0; virtual int getMetaTypeId() const = 0; @@ -93,6 +95,16 @@ namespace BlackMisc template static void convertFromJson(const QJsonObject &, T &object, ...) { throw CVariantException(object, "convertFromJson"); } + template + static QJsonObject toMemoizedJson(const T &object, decltype(static_cast(object.toMemoizedJson()), 0)) { return object.toMemoizedJson(); } + template + static QJsonObject toMemoizedJson(const T &object, ...) { return toJson(object, 0); } + + template + static void convertFromMemoizedJson(const QJsonObject &json, T &object, decltype(static_cast(object.convertFromMemoizedJson(json)), 0)) { object.convertFromMemoizedJson(json); } + template + static void convertFromMemoizedJson(const QJsonObject &json, T &object, ...) { convertFromJson(json, object, 0); } + template static uint getValueHash(const T &object, decltype(static_cast(qHash(object)), 0)) { return qHash(object); } template @@ -145,6 +157,14 @@ namespace BlackMisc { CValueObjectMetaInfoHelper::convertFromJson(json, cast(object), 0); } + virtual QJsonObject toMemoizedJson(const void *object) const override + { + return CValueObjectMetaInfoHelper::toMemoizedJson(cast(object), 0); + } + virtual void convertFromMemoizedJson(const QJsonObject &json, void *object) const override + { + CValueObjectMetaInfoHelper::convertFromMemoizedJson(json, cast(object), 0); + } virtual void unmarshall(const QDBusArgument &arg, void *object) const override { arg >> cast(object);