Как изменить значение QJsonObject в иерархии QJson без использования копий?

В настоящее время я использую 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, не затрачивая на это все усилия !!!

14

Решение

Согласно информации от разработчика Qt, который действительно написал QJson в Qt5 —

В настоящее время в Qt включена реализация «только для чтения», обеспечивающая средства синтаксического анализа. У него есть намерение расширить дизайн с поддержкой ссылок в будущем, но это еще не сделано.

8

Другие решения

Потратив три часа своей жизни, я могу подтвердить, что на сегодняшний день это все еще невозможно с 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.

12

По вопросам рекламы [email protected]