#include "qtjsonsettings.h" #include #include namespace { void processReadKey(QString& key, QSettings::SettingsMap &map, const QVariant& element) { switch (element.type()) { case QVariant::Map: { auto vMap = element.toMap(); auto it = vMap.constBegin(); auto end = vMap.constEnd(); for (; it != end; ++it) { key.append(it.key()); key.append("/"); processReadKey(key, map, it.value()); } break; } case QVariant::List: { QVariantList list = element.toList(); map.insert(key + "size", list.count()); for (int i = 0; i < list.count(); ++i) { key.append(QString::number(i + 1)); key.append("/"); processReadKey(key, map, list.at(i)); } break; } default: map.insert(key.left(key.size() - 1), element); } key.truncate(key.lastIndexOf("/", -2) + 1); } QVariant processWriteKey(QVariant& root, const QString& key, const QVariant& value) { int slashPos = key.indexOf('/'); // If it is key if (slashPos < 0) { QVariantMap map = root.toMap(); /** TODO VERY UGLY array detecting method * Key size always placed after all numeric keys (array indexes) * Convert root map to list and return it. * Warning. Index starts with 1 */ if (key == "size") { QVariantList list; for (int i = 1; i <= value.toInt(); ++i) { list.append(map.value(QString::number(i))); } return list; } else { map.insert(key, value); return map; } } // get group name QString groupName = key.left(slashPos); // if name is number then it's row of array, convert to list QVariantMap map = root.toMap(); QVariant item = map.value(groupName); map.insert(groupName, processWriteKey(item, key.mid(slashPos + 1), value)); return map; } } const QSettings::Format QtJsonSettings::json_format = QSettings::registerFormat("json", readJsonFile, writeJsonFile); bool QtJsonSettings::readJsonFile(QIODevice &device, QSettings::SettingsMap &map) { QJsonParseError error; auto document = QJsonDocument::fromJson(device.readAll(), &error); if (QJsonParseError::NoError == error.error) { if (!document.isEmpty()){ QString str; processReadKey(str, map, document.toVariant()); } } else { qWarning() << error.errorString(); } return true; } bool QtJsonSettings::writeJsonFile(QIODevice &device, const QSettings::SettingsMap &map) { QVariant resultMap; auto it = map.constBegin(); auto end = map.constEnd(); for (; it != end; ++it) { resultMap = processWriteKey(resultMap, it.key(), it.value()); }; device.write(QJsonDocument::fromVariant(resultMap).toJson()); return true; }