diff --git a/src/blackmisc/valuecache.cpp b/src/blackmisc/valuecache.cpp index d22b5b8bd..53d2ec9d8 100644 --- a/src/blackmisc/valuecache.cpp +++ b/src/blackmisc/valuecache.cpp @@ -312,10 +312,8 @@ namespace BlackMisc { return CStatusMessage(this).error("Invalid JSON format in %1") << file.fileName(); } - CVariantMap storedValues; - storedValues.convertFromJson(json.object()); - storedValues.insert(*it); - json.setObject(storedValues.toJson()); + auto object = json.object(); + json.setObject(it->mergeToJson(object)); if (!(file.seek(0) && file.resize(0) && file.write(json.toJson()) > 0 && file.checkedClose())) { @@ -343,10 +341,25 @@ namespace BlackMisc return CStatusMessage(this).error("Failed to create directory %1") << dir; } - const QStringList entries(QDir(dir).entryList({ "*.json" }, QDir::Files)); - for (const auto &filename : entries) + QMap keysInFiles; + for (const auto &key : keys) { - QFile file(dir + "/" + filename); + keysInFiles[key.section('/', 0, 0)].push_back(key); + } + if (keys.isEmpty()) + { + for (const auto &filename : QDir(dir).entryInfoList({ "*.json" }, QDir::Files)) + { + keysInFiles.insert(filename.completeBaseName(), {}); + } + } + for (auto it = keysInFiles.cbegin(); it != keysInFiles.cend(); ++it) + { + QFile file(dir + "/" + it.key() + ".json"); + if (! file.exists()) + { + continue; + } if (! file.open(QFile::ReadOnly | QFile::Text)) { return CStatusMessage(this).error("Failed to open %1: %2") << file.fileName() << file.errorString(); @@ -357,11 +370,8 @@ namespace BlackMisc return CStatusMessage(this).error("Invalid JSON format in %1") << file.fileName(); } CVariantMap temp; - temp.convertFromJson(json.object()); - if (! keys.isEmpty()) - { - temp.removeByKeyIf([&keys](const QString & key) { return ! keys.contains(key); }); // TODO optimize by skipping files - } + temp.convertFromJson(json.object(), it.value()); + if (it.value().isEmpty()) { temp.convertFromJson(json.object()); } temp.removeDuplicates(currentValues); o_values.insert(temp, QFileInfo(file).lastModified().toMSecsSinceEpoch()); } diff --git a/src/blackmisc/variantmap.cpp b/src/blackmisc/variantmap.cpp index 199d931b8..8915e9dd3 100644 --- a/src/blackmisc/variantmap.cpp +++ b/src/blackmisc/variantmap.cpp @@ -14,9 +14,8 @@ namespace BlackMisc { - QJsonObject CVariantMap::toJson() const + QJsonObject &CVariantMap::mergeToJson(QJsonObject &json) const { - QJsonObject json; for (auto it = cbegin(); it != cend(); ++it) { json.insert(it.key(), it.value().toJson()); @@ -24,6 +23,13 @@ namespace BlackMisc return json; } + QJsonObject CVariantMap::toJson() const + { + QJsonObject json; + mergeToJson(json); + return json; + } + void CVariantMap::convertFromJson(const QJsonObject &json) { clear(); @@ -35,4 +41,17 @@ namespace BlackMisc } } + void CVariantMap::convertFromJson(const QJsonObject &json, const QStringList &keys) + { + clear(); + for (const auto &key : keys) + { + auto value = json.value(key); + if (value.isUndefined()) { continue; } + CVariant var; + var.convertFromJson(value.toObject()); + insert(key, var); + } + } + } diff --git a/src/blackmisc/variantmap.h b/src/blackmisc/variantmap.h index 3481dcf31..09a2aa118 100644 --- a/src/blackmisc/variantmap.h +++ b/src/blackmisc/variantmap.h @@ -56,11 +56,18 @@ namespace BlackMisc //! Move assignment operator. CVariantMap &operator =(CVariantMap &&other) noexcept { CDictionary::operator =(std::move(other)); return *this; } + //! Insert values from this map into an existing JSON object. + QJsonObject &mergeToJson(QJsonObject &json) const; + //! \copydoc BlackMisc::CValueObject::toJson QJsonObject toJson() const; //! \copydoc BlackMisc::CValueObject::convertFromJson void convertFromJson(const QJsonObject &json); + + //! \copydoc BlackMisc::CValueObject::convertFromJson + //! Convert only keys present in list argument. + void convertFromJson(const QJsonObject &json, const QStringList &keys); }; }