delete unknown json objects + write missing objects to config file

This commit is contained in:
2026-08-16 12:17:50 +02:00
parent 02bb7e43d8
commit 4f544981c1
13 changed files with 132 additions and 48 deletions
+78 -4
View File
@@ -7,6 +7,51 @@
namespace ZShell::config {
namespace {
bool isStringArray(const QJsonArray& arr) {
for (const auto& v : arr) {
if (!v.isString()) return false;
}
return true;
}
bool jsonValueMatchesType(const QJsonValue& val, QMetaType type) {
switch (val.type()) {
case QJsonValue::Bool:
return type.id() == QMetaType::Bool;
case QJsonValue::Double:
switch (type.id()) {
case QMetaType::Int:
case QMetaType::UInt:
case QMetaType::LongLong:
case QMetaType::ULongLong:
case QMetaType::Double:
case QMetaType::Float:
return true;
default:
return false;
}
case QJsonValue::String:
return type.id() == QMetaType::QString;
case QJsonValue::Array:
if (type.id() == QMetaType::QStringList)
return isStringArray(val.toArray());
return type.id() == QMetaType::QVariantList;
case QJsonValue::Object:
case QJsonValue::Null:
case QJsonValue::Undefined:
default:
return false;
}
}
} // namespace
ConfigObject::ConfigObject(QObject* parent) : ConfigNode(parent) {}
void ConfigObject::loadFromJson(const QJsonValue& json) {
@@ -14,6 +59,7 @@ void ConfigObject::loadFromJson(const QJsonValue& json) {
const auto* meta = metaObject();
QSet<QString> known;
QSet<QString> invalid;
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
auto prop = meta->property(i);
@@ -34,6 +80,15 @@ void ConfigObject::loadFromJson(const QJsonValue& json) {
if (!prop.isWritable()) continue;
if (!jsonValueMatchesType(jsonVal, prop.metaType())) {
qWarning() << "Config: type mismatch for" << key << "in"
<< meta->className() << "- expected"
<< prop.metaType().name() << "got value" << jsonVal
<< "- resetting to default";
invalid.insert(key);
continue;
}
if (prop.metaType().id() == QMetaType::QStringList) {
QStringList list;
const auto jsonArr = jsonVal.toArray();
@@ -56,10 +111,12 @@ void ConfigObject::loadFromJson(const QJsonValue& json) {
m_extras = {};
for (auto it = obj.begin(); it != obj.end(); ++it) {
if (!known.contains(it.key())) {
if (!known.contains(it.key()) || invalid.contains(it.key())) {
m_extras.insert(it.key(), it.value());
}
}
materializeDefaults();
}
QJsonValue ConfigObject::toJson() const {
@@ -104,9 +161,6 @@ QJsonValue ConfigObject::toJson() const {
obj.insert(key, QJsonValue::fromVariant(value));
}
for (auto it = m_extras.begin(); it != m_extras.end(); ++it)
obj.insert(it.key(), it.value());
if (obj.isEmpty()) return QJsonValue::Undefined;
return obj;
@@ -159,6 +213,26 @@ QList<ConfigNode*> ConfigObject::childNodes() const {
return nodes;
}
void ConfigObject::materializeDefaults() {
const auto* meta = metaObject();
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
const auto prop = meta->property(i);
const auto key = QString::fromUtf8(prop.name());
if (auto* const node = prop.read(this).value<ConfigNode*>()) {
node->materializeDefaults();
continue;
}
if (!prop.isWritable()) continue;
if (m_global) continue;
m_loadedKeys.insert(key);
}
}
void ConfigObject::syncValuesFromGlobal() {
const auto* meta = metaObject();