Qt — передача ссылки на QJsonObject или QJsonArray

Я делаю редактор данных формата Json с поддержкой Qt treeview и Qt Json.
Я хочу передать ссылочный параметр QJsonObject или QJsonArray в функцию.

Это работает:

void makeJsonData(QJsonObject &obj) {
obj.insert("key", 1234);
}

//call makeJsonData()
QJsonObject jobj;
makeJsonData(jobj);
int keysize = jobj.keys().size(); //1, OK.

Но не с этим:

//QJsonValue, because it can handle both QJsonObject and QJsonArray
void makeJsonData(QJsonValue &obj) {
obj.toObject().insert("key", 1234); //obj is QJsonObject
}

//call makeJsonData()
QJsonObject jobj;
makeJsonData(QJsonValue::fromVariant(jobj)); //fromVariant() to cast QJsonObject to QJsonValue
int keysize = jobj.keys().size(); //0, Fail.

Похоже, QJsonValue :: toObject () просто копирует параметр ..
Как я могу использовать ссылки как QJsonObject, так и QJsonArray с одним типом параметра?

0

Решение

Есть несколько способов решить вашу проблему:

Опция 1 (как упоминалось в моем комментарии)

Динамическое приведение может быть использовано так:

bool makeJsonData(void* obj) {
QJsonObject* asObj = dynamic_cast<QJsonObject*>(obj);
QJsonArray* asArray = dynamic_cast<QJsonArray*>(obj);

if (asObj) {
//do what you would if it were an object
}
else if (asArray) {
//do what you would if it were an array
}
else {
//cast fail. Returning false to tell the caller that they passed bad data
//an alternate (probably better) would be to throw an exception
return false;
}
}

Вариант 2

Я честно чувствую, что это бизнес с void* это неправильный способ сделать это. дела void* материал почти всегда пахнет кодом (он убирает проверки во время компиляции, которые не дают нам встать на ноги), и в этом случае я думаю, что то, как вы это делаете, требует работы. Также, dynamic_cast требует RTTI который не всегда может быть включен (поддержка компилятора, проблемы с производительностью и т. д.).

Я посмотрел на заголовки Qt на моей машине и, насколько я могу судить, QJsonObject а также QJsonArray на самом деле не наследовать от чего-либо, поэтому идти по пути изменения void* к базовому типу, чтобы сохранить видимость проверки типов, не совсем сработает.

Что бы я сделал, было бы это:

  • Сделайте два отдельных метода. Один для обработки массивов и один для обработки объектов. У них разные методы и разные вещи, которые вы можете сделать, так что для меня это имеет смысл. Вы могли бы даже сохранить то же имя, чтобы они были перегружены.
  • Есть другой метод с вашими общими вещами в нем. Я предполагаю, что ваша функция пытается добавить некоторые данные в массив или объект, который передается. Сделайте метод, который создает данные (т.е. QJsonObject createJsonData()) и вызовите его внутри обоих ваших методов, упомянутых выше.

Идея состоит в том, чтобы сохранить повторение кода при сохранении проверки типов. Время, которое вы тратите на создание одного дополнительного метода для обработки обоих случаев, может быть намного меньше, чем время, которое вы потратите на отладку кода после случайной передачи чего-либо void* указатель, который вы никогда не хотели передавать.

Вариант 3

Вы также можете использовать QJsonValueизмените тип возвращаемого значения функции на QJsonValueи заставить его вернуть новый объект без изменения оригинала. Кроме того, QJsonValue класс развлекается isArray/isObject методы, которые вы могли бы использовать, чтобы сделать что-то вроде упомянутых ранее. Пример:

QJsonValue makeJsonData(const QJsonValue& val) {
if (val.isObject()) {
QJsonObject obj = val.toObject();
//do your stuff, modifying obj as you please (perhaps calling another method so that this can have less repetition
return QJsonValue(obj);
}
else if (val.isArray()) {
QJsonArray arr = val.toArray();
//do your stuff, modifying arr as you please (perhaps calling another method so that this can have less repetition
return QJsonValue(arr);
}
else {
throw "Invalid Value Type";
}
}

Честно говоря, я предпочитаю эту схему, но я знаю, что есть причины для того, чтобы вы пошли тем путем, который вы упомянули, например, чтобы избежать беспричинного выделения памяти.

1

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


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