如何将json对象转换为QObject?

时间:2016-08-24 12:05:58

标签: c++ json qt serialization reflection

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
  }
}

的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 );

}

JSON是一个字符串,我需要通过一个模板函数将其转换为FPersonInfo。 有没有已知的算法?

2 个答案:

答案 0 :(得分: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();
    }
}

要记住的一点是,您要转换的每个QObject类型都必须有一个标有Q_INVOKABLE的默认构造函数,在您的情况下使用它可能看起来像这样(假设您将这些方法放入名为Utils的课程

QString json = QString(); //load json from somewhere
FPersonInfo*  person = (FPersonInfo*) Utils::fromJson(FPersonInfo::staticMetaObject, json);

答案 1 :(得分:0)

我将此实现为开放式图书馆:https://github.com/carlonluca/lqobjectserializer

定义结构:

explicit

完成:

std::vector<int, stateful_allocator<int>> x(stateful_allocator<int>{0});

您还需要像往常一样在元对象系统中注册类型。