将QObject的实例转换为JSON
我用一些代码将任意QObject子类转换为JSON。如果它们是指向子类的指针,我可以转换它们,但我很好奇是否可以转换实例(前提是子类实现了复制构造函数)。是否有一些疯狂的方法可以使用模板或将QObject的实例转换为JSON,json,qt,qvariant,Json,Qt,Qvariant,我用一些代码将任意QObject子类转换为JSON。如果它们是指向子类的指针,我可以转换它们,但我很好奇是否可以转换实例(前提是子类实现了复制构造函数)。是否有一些疯狂的方法可以使用模板或QMetaType提供的类型信息来复制QObject子类的实例,而不知道它是什么?ToJson代码位于一个不知道子类的类中 我认为可以使用QMetaType::create或类似的东西,但我还没有弄清楚如何实际复制子类实例的属性 以下是我的转换代码: QJsonValue ToJson(QVariant val
QMetaType
提供的类型信息来复制QObject
子类的实例,而不知道它是什么?ToJson
代码位于一个不知道子类的类中
我认为可以使用QMetaType::create
或类似的东西,但我还没有弄清楚如何实际复制子类实例的属性
以下是我的转换代码:
QJsonValue ToJson(QVariant value){
switch(value.type()){
case QVariant::Int:
case QVariant::Double:
return value.toDouble();
////Other cases, etc...
case QVariant::UserType:
QObject* obj_ptr = qvariant_cast<QObject*>(value);
if(obj_ptr) // value was originally a pointer to a QObject, works correctly
return ToJson(obj_ptr);
else { // value was orginally an instance of a QObject subclass
std::string t = value.typeName(); //returns "MyQObject"
int id = QMetaType::type(t.c_str()); //returns the id of the derived class
void* v = QMetaType::create(id, &value); //passing &value does nothing
obj_ptr = static_cast<QObject*>(v);
return ToJson(obj_ptr); //works, but resulting fields are all default
}
}
}
QJsonObject ToJson(QObject* o){
QJsonObject obj;
auto mo = o->metaObject();
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
QVariant value = o->property(mo->property(i).name());
obj[mo->property(i).name()] = ToJson(value);
}
return obj;
}
有没有办法处理上面
test1
所示的情况 长话短说:不。无法在容器或QVariant
中按值存储QObject
s
Qt禁止复制QObject和所有继承类。Q_OBJECT
宏的强制命令将在新定义的类中禁用任何复制构造函数
在MyObject
类中定义的复制构造函数缺少基类构造函数调用。如果QObject
有一个复制构造函数,它将是这样的:
MyQObject(const MyQObject& other) :
QObject(other) // this will NEVER compile
{
i = other.i;
db = other.db;
}
编译器可能会给您一个警告,但允许您使用这样的构造函数,即使每次通过值传递MyObject
的实例时,它都会导致未定义的行为或切片
此外,缔约国声明如下:
存储在各种容器中的值可以是任何可赋值的
数据类型。要进行限定,类型必须提供默认构造函数
复制构造函数和赋值运算符。这涵盖了大多数数据
您可能希望存储在容器中的类型,包括基本类型
类型(如int和double)、指针类型和Qt数据类型(如
QString、QDate和QTime,但它不包括QObject或任何QObject
子类(QWidget、QDialog、QTimer等)
因此,除非将它们存储为指针,否则不能将QObject
和派生类存储在Qt容器中,因为QObject的副本被设计禁用
此外,如果您想利用多态行为,就必须使用指针,即使在代码中没有显式需要强制转换到派生类,就我所见。如果你真的需要在某个地方诉诸于铸造,你可以考虑让你的Tojson成为模板函数。p> 有一个解决方案,但请谨慎使用,因为它仅在以下情况下合理/适用:
- 所讨论的类主要是数据存储类
- 如果这些类不是从
QObject
- 最重要的是,让类从
继承的唯一原因是它可以具有元属性。QObject
QObject
,而不是为了获取元信息,那么如果您试图按值存储该类(正如G.Giordano在其回答中所解释的),则几乎肯定是错误地使用了该类
除了误用注意事项,为了通过值存储QObject
子类的QVariant
,您可以使用QMetaType::create
方法并将用户类型id和yourQVariant.constData()
传递给它
例如:
MyQObject obj;
obj.db = 11.1;
QVariant value = QVariant::fromValue(obj);
std::string t = value.typeName();
int id = QMetaType::type(t.c_str());
void* v = QMetaType::create(id, value.constData());
obj_ptr = static_cast<QObject*>(v);
QJsonValue json = ToJson(obj_ptr); //json contains db = 11.1
MyQObject对象;
obj.db=11.1;
QVariant value=QVariant::fromValue(obj);
std::string t=value.typeName();
int id=QMetaType::type(t.c_str());
void*v=QMetaType::create(id,value.constData());
obj_ptr=静态铸造(v);
QJsonValue json=ToJson(obj_ptr)//json包含db=11.1
使用map.insert(“myobj”,QVariant::fromValue(&obj))存储代码>并使用QObject*obj_ptr=qvariant_cast(值)进行检索代码>工作正常。我不想将其强制转换为派生对象,因为转换器不知道派生类。另外,我的问题是,我是否可以处理包含QObject实例而不是指针的映射。由于我的派生对象具有有效的副本构造函数,因此它实际上可以作为实例存储在容器中,但我的ToJson
函数当前只能处理指针。我将用一个模板版本来搞乱,看看发生了什么。我对我的问题进行了大量编辑,以更好地解释我的意图。感谢您的投入,感谢您的澄清。我再次编辑了我的答案,希望它能有所帮助。我的复制构造函数确实调用了默认的基类构造函数(QObject()
),但我的示例代码意外地忽略了这一点。为了完整起见,我将添加它
MyQObject(const MyQObject& other) :
QObject(other) // this will NEVER compile
{
i = other.i;
db = other.db;
}
MyQObject obj;
obj.db = 11.1;
QVariant value = QVariant::fromValue(obj);
std::string t = value.typeName();
int id = QMetaType::type(t.c_str());
void* v = QMetaType::create(id, value.constData());
obj_ptr = static_cast<QObject*>(v);
QJsonValue json = ToJson(obj_ptr); //json contains db = 11.1