如何将json对象转换为QObject?

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.有没有已知的算法?

Elu*_*tar 5

我自己一直在研究这个问题,到目前为止我有一个非常粗略的实现,遗憾的是根本不支持列表,没有通用的方法来确定列表的类型然后添加它,你可以如果适合您,则需要对特定列表类型的硬代码支持.

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)