Art*_*nov 3 c++ reflection serialization qt json
Json结构是C++类似结构(结构或sturcts数组,数组和基本类型).我需要将JSON对象转换为具有指定属性的指定QObject(通过QObject字段).
例如,json:
{
"name": "Andrew",
"age" 33,
"identifiers": [32, 45, 67, 78],
"more": {
"gps": "44.9064', W073° 59.0735'",
"valid": true
}
}
Run Code Online (Sandbox Code Playgroud)
的QObject:
class FMoreInfo : public QObject {
Q_OBJECT
Q_PROPERTY( QString gps );
Q_PROPERTY( bool valid );
}
class FPersonInfo : public QObject {
Q_OBJECT
Q_PROPERTY( QString name );
Q_PROPERTY( int32 age );
Q_PROPERTY( QVector<int32> identifiers );
Q_PROPERTY( FMoreInfo more );
}
Run Code Online (Sandbox Code Playgroud)
JSON是一个字符串,我需要通过一个模板函数将其转换为FPersonInfo.有没有已知的算法?
我自己一直在研究这个问题,到目前为止我有一个非常粗略的实现,遗憾的是根本不支持列表,没有通用的方法来确定列表的类型然后添加它,你可以如果适合您,则需要对特定列表类型的硬代码支持.
QObject* Utils::fromJson(const QMetaObject& meta, QString& json)
{
auto jsonObject = QJsonDocument::fromJson(json.toLatin1()).object();
return fromJson(&meta, jsonObject);
}
QObject* Utils::fromJson(const QMetaObject* meta, QJsonObject& jsonObject)
{
QObject* object = meta->newInstance();
int propertyStart = QObject::staticMetaObject.propertyCount();
for (int i = propertyStart; i < meta->propertyCount(); ++i) {
QMetaProperty property = meta->property(i);
if (!property.isWritable())
continue;
if (!jsonObject.contains(property.name()))
continue;
auto value = jsonValueToProperty(object, property, jsonObject.value(property.name()));
property.write(object, value);
}
return object;
}
QVariant Utils::jsonValueToProperty(QObject* object, QMetaProperty& property, QJsonValue value)
{
auto type = property.userType();
auto typeName = QString(property.typeName());
if (value.isArray()) {
//todo array
} else if (value.isObject()) {
switch (type) {
default:
auto jsonObject = value.toObject();
return QVariant::fromValue(fromJson(QMetaType::metaObjectForType(type), jsonObject));
break;
}
//todo other meta object types
} else {
//primitive types
return value.toVariant();
}
}
Run Code Online (Sandbox Code Playgroud)
需要记住的是,要转换的每个QObject类型都必须有一个标记的默认构造函数Q_INVOKABLE,为你的情况使用它可能看起来像这样(假设你将这些方法放入一个名为Utils
QString json = QString(); //load json from somewhere
FPersonInfo* person = (FPersonInfo*) Utils::fromJson(FPersonInfo::staticMetaObject, json);
Run Code Online (Sandbox Code Playgroud)