Когда у меня есть свой собственный тип со стандартными свойствами типов Qt, я могу сделать что-то вроде этого:
for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); i++) {
auto key = metaObject()->property(i).name();
setProperty(key, other.property(key));
}
Я также могу создать свой собственный тип с конструкторами, принимающими QJsonObject , QVariant и любые другие типы, не явные [например, Вы можете ввести QJsonObject json = MyType();
]
Я реализовал QVariant конструктор, потому что other.property(key)
возвращает QVariant . Я надеялся, что это сработает.
Я также могу создавать операторы этого типа, например
virtual operator const QVariant() const {...}
или
virtual operator const QJsonObject() const {...}
Но если у меня есть свой пользовательский класс с Q_PROPERTY(MyType....)
, я не могу просто использовать цикл с начала этого поста.
Итак, вопрос: как я могу реализовать универсальную систему сериализации Qt, используя только конструкторы, операторы присваивания и систему свойств Qt (также Q_DECLARE
и qRegister
)?
Мои попытки можно найти здесь:
https://gitlab.com/luntik2012/goodies/blob/master/rfproperty.h
образец выделенного класса:
class Test : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
public:
Test() = default;
Test(const QJsonObject &json)
: QObject()
{
// just imagine it will work dynamically. I have my own macro performing this
for(int i = staticMetaObject.propertyOffset(); i < metaObject()->propertyCount(); i++)
{
auto key = metaObject()->property(i).name();
setProperty(key, json[key]);
}
}
// The same thing as in Json constructor, just shotrened the snippet
Test(const Test &other) : QObject() { Q_UNUSED(other); }
public:
Test& operator =(const Test &other) {
for(int i = staticMetaObject.propertyOffset(); i < metaObject()->propertyCount(); i++)
{
auto key = metaObject()->property(i).name();
setProperty(key, json[key]);
}
return *this;
}
Test& operator =(const QVariant &variant) {
*this = variant.value<Test>();
return *this;
}
signals:
void nameChanged();
public:
Q_INVOKABLE QString name() const { return m_name; }
virtual operator const QJsonObject() const {
return QJsonObject { { "name", m_name } };
}
virtual operator const QVariant() const {
return QVariant(Test::operator const QJsonObject());
}
private:
QString m_name;
};
Q_DECLARE_METATYPE(Test)
Теперь вы можете представить себе тот же класс, скажем, Check, но со свойством Test вместо QString. И я хочу просто написать
QJsonObject json;
json = Check(...);
Он работает со стандартными типами, но я не знаю, что делать со своими.
Отлично, я хочу использовать такой «оператор QJsonObject» для сериализации любых типов в QObject. Например, наследуйте QList, реализуйте эти операторы и используйте как любые другие объекты для сериализации