Qt, QVariant, JSON and enums

Qt, QVariant, JSON and enums

本文关键字:enums and QVariant Qt JSON      更新时间:2023-10-16

我试图弄清楚我应该如何在Qt中使用枚举,以便我将它们打包在QVariant中并将它们转换为QJsonValue和后来的JSON。

根据文档,我最终声明了我的枚举:

enum BeautifulColors { Red, Green, Blue };
Q_DECLARE_METATYPE(BeautifulColors);

这样我就可以在QVariant上使用setValue(..)来设置我自定义的枚举值。

问题是QJsonValue::fromVariant(),文档说:

将变量转换为QJsonValue并返回它。(...)对于所有其他QVariant类型,将转换为QString尝试。如果返回的字符串为空,QJsonValue将为Null

转换到QString失败,并且我的QJsonValue对象最终为Null。

接下来的文档是令人困惑的:在QObject中有一个Q_EUM宏用于枚举定义。然而,由于QObject是不可复制的,我不认为QVariant应该持有它。当然有一些hack是让它工作,但这不是我想要的。在Qt中定义枚举的推荐方法是什么,以便它们可以用作数据类型并转换为JSON并从JSON中读取?

尝试如下:

rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
#include <QObject>
class Rectangle : public QObject
{
    Q_OBJECT
public:
    enum Color
    {
        Red,
        Green,
        Blue,
    };
    Q_ENUM(Color)
    Rectangle(double x, double y, Color color, QObject *parent = 0);
private:
    double _x;
    double _y;
    Color _color;
};
#endif
rectangle.cpp
#include "rectangle.h"
Rectangle::Rectangle(double x, double y, Rectangle::Color color, QObject *parent)
    : QObject(parent)
    , _x(x)
    , _y(y)
    , _color(color)
{
}
main.cpp
#include <QVariant>
#include <QDebug>
#include <QString>
#include "rectangle.h"
int main(int argc, char *argv[])
{
    int id = qMetaTypeId<Rectangle::Color>();
    Rectangle::Color blueColor = Rectangle::Blue;
    QVariant myVariant;
    myVariant.setValue(blueColor);
    qDebug() << id;
    qDebug() << myVariant.toString();
}

现在它有了一个类型id和一个字符串表示!但不是保存它的类:

int idRectangle = qMetaTypeId<Rectangle>();

不编译,我不能注册它与Q_DECLARE_MEATYPE,因为它没有构造函数。如果我需要qvariant toString()与任何类一起工作该怎么办?

第二更新

使用Q_GADGET宏,我现在为枚举和保存它的类获得了一个(不同的)类型id。但是,我仍然只得到enum的字符串表示形式。

需要Q_ENUMQ_ENUMS来生成toString/fromString功能所需的QMetaEnum结构。

为了让moc处理它们并生成必要的代码,它们需要被放置在带有Q_OBJECT标记的QObject派生类中或任何带有Q_GADGET标记的类中。

当存储枚举值时,定义它们的类并不是存储在变体中的类。您可以将该类看作是enum的"命名空间"。

我把剩下的弄清楚了,为了能够使用QVariant::toString(),必须为QVariant持有的类型注册转换。

这是由KDAB在Qt 5.2 (http://log.cedricbonhomme.org/55/66102.html)中添加的,但在文档QVariant::toString()中没有提到!(

无论如何,它也适用于普通枚举,下面的示例将输出"Apple"

enum Fruit {
    Apple,
    Pear,
    Orange
};
Q_DECLARE_METATYPE(Fruit)
QString Fruit2QString(Fruit fruit)
{
    switch(fruit)
    {
        case Apple:
            return "Apple";
        case Pear:
            return "Pear";
        case Orange:
            return "Orange";
    }
    return "asdf";
}
int main(int argc, char *argv[])
{
    std::function<QString(Fruit)> f = &Fruit2QString;
    bool success = QMetaType::registerConverter<Fruit, QString>(f);
    Q_ASSERT(success);
    QVariant v;
    v.setValue(Fruit::Apple);
    qDebug() << v.toString();
}