В настоящее время я использую Qt5.0 с базовой библиотекой QJson для обработки некоторых данных для разрабатываемой программы.
Чтобы установить сцену для этого вопроса, я предоставлю вам некоторые данные JSON, которые иллюстрируют мою проблему:
{
"CLOCKS": [
{
"ID": "clk",
"MAX": 2e+08,
"MIN": 1e+07,
"VALUE": "no_clock"
},
{
"ID": "memclk",
"MAX": 2e+08,
"MIN": 1e+07,
"VALUE": "memclk"
}
]
}
Здесь у нас есть родительский объект QJsonObject, содержащий один ключ "CLOCKS". Значение для этого ключа - QJsonArray QJsonObjects, который содержит несколько пар ключ/значение, которые содержат мои данные.
Если бы я хотел получить QJsonObject с id 'clk', я в настоящее время использую такой код:
// imagine m_data is my parent QJsonObject
QJsonArray clocks = m_data["CLOCKS"].toArray();
foreach (const QJsonValue & value, clocks) {
QJsonObject obj = value.toObject();
if (obj["ID"].toString() == "clk") {
return obj;
}
}
Это прекрасно работает, и библиотека до сих пор была замечательной. Однако я недавно начал сталкиваться с проблемами, когда хочу получить QJsonObject reference для модификации вместо копии.
Итак, мой вопрос заключается в том, что, учитывая предоставленные примеры данных, как получить ссылку QJsonObject, чтобы изменить пары ключ/значение в желаемом объекте данных синхронизации. Проблема проявляется, ИМО из-за того, что вы можете получить QJsonValueRefs, которые являются ссылками на записи значений... но чтобы фактически получить доступ к данным внутри этого (если это значение является другим массивом/объектом), вы должны преобразовать, используя toArray(), toObject() и т.д. Эти функции возвращают только копии, а не ссылки, создающие барьер для итерации иерархии объектов со ссылками.
Единственный способ, с которым я пришел, чтобы обойти это, - создать копию всего "CLOCKS" QJsonArray, найти объект, который я хочу, затем удалить его и вставить в него с измененными данными... и, наконец, назначьте весь массив обратно к ключу CLOCKS в родительском объекте. Это кажется мне громоздким для меня, что я чувствую, что делаю что-то неправильно, и должен быть лучший способ.
Чтобы поддержать это, вот как выглядит мой код до сих пор... просто чтобы изменить "VALUE" для одного из часов QJsonObjects:
QJsonArray resets = m_data.value(TAG_RESETS).toArray();
// get a copy of the QJsonObject
QJsonObject obj;
foreach (const QJsonValue & value, resets) {
QJsonObject o = value.toObject();
if (o.value(TAG_ID).toString() == id) {
obj = o;
break;
}
}
// modify the object
obj[TAG_VALUE] = "NEW VALUE";
// erase the old instance of the object
for (auto it = resets.begin(); it != resets.end(); ++it) {
QJsonObject obj = (*it).toObject();
if (obj.value(TAG_ID).toString() == id) {
resets.erase(it);
// assign the array copy which has the object deleted
m_data[TAG_RESETS] = resets;
break;
}
}
// add the modified QJsonObject
resets.append(obj);
// replace the original array with the array containing our modified object
m_data[TAG_RESETS] = resets;
Я знаю, что это может быть сокращено немного, но все же кажется, что должен быть лучший способ изменить одно значение в иерархии объектов QJson, не прибегая к этим усилиям.