В настоящее время я использую 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 с идентификатором ‘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 ссылка для модификации вместо копии.
Поэтому мой вопрос заключается в том, что, учитывая предоставленные примеры данных, как получить ссылку на QJsonObject, чтобы изменить пары ключ / значение в желаемом объекте данных часов. Проблема проявляется, IMO, из-за того, что вы можете получить QJsonValueRefs, которые являются ссылками на записи значений … но для фактического доступа к данным внутри этого (если значением является другой массив / объект), вы должны конвертировать, используя toArray (), функции toObject () и т. д. Эта функция возвращает только копии, а не ссылки, создавая барьер для итерации по иерархии объектов со ссылками.
Единственный способ обойти это до сих пор — создать копию всего QJsonArray «CLOCKS», найти нужный объект, затем удалить его и заново вставить с измененными данными … и, наконец, назначить весь объект. массив обратно к ключу «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, не затрачивая на это все усилия !!!
Согласно информации от разработчика Qt, который действительно написал QJson в Qt5 —
В настоящее время в Qt включена реализация «только для чтения», обеспечивающая средства синтаксического анализа. У него есть намерение расширить дизайн с поддержкой ссылок в будущем, но это еще не сделано.
Потратив три часа своей жизни, я могу подтвердить, что на сегодняшний день это все еще невозможно с Qt 5.4. Вы можете изменять объекты JSON, но не вложенные объекты JSON.
Проблема в том, что такой код:
json["aa"].toObject()["bb"] = 123;
по сути, означает следующее:
QJsonObject temp = json["aa"].toObject();
temp["bb"] = 123;
и с тех пор temp
это не ссылка, а объект (и toObject()
не возвращает ссылку), назначение компилируется, но затем отбрасывается.
По сути, это сводится к тому, что невозможно получить ссылку на объект, который вы только что создали, то есть вы не можете создать их слева направо, то есть aa [«bb»] -> aa [«bb»] [«cc «] и т. д. — вы не можете получить ссылку на aa [» bb «], только копию его значения.
Что возможно, хотя это воссоздать JSON с новой добавленной стоимостью, как описано здесь: https://forum.qt.io/topic/25096/modify-nested-qjsonvalue/4 — обратите внимание, что это продолжает воссоздавать объект каждый раз, когда он вызывается, и по сути является катастрофой использования памяти, но это все, что в настоящее время позволяет Qt.