setProperty()返回false

时间:2015-10-10 21:47:42

标签: c++ json qt deserialization moc

我尝试将QVariantMap转换为源自QObject的自定义类,但我从setProperty()获得false的返回值在设置我的枚举类型的属性时。代码如下:

MessageHeader.h 文件:

// deserialization class header
class MessageHeader : public QObject
{
    Q_OBJECT

public:
    MessageHeader(QObject *parent = 0);
    ~MessageHeader();

    enum class MessageType
    {
        none = 0,
        foo = 1,
        baa = 2
    };

    Q_ENUM(MessageType)
    Q_PROPERTY(MessageType type READ getType WRITE setType)
    Q_PROPERTY(int ContentLength READ getContentLength WRITE setContentLength)

    void setType(MessageType type);
    void setContentLength(int ContentLength);
    MessageType getType();
    int getContentLength();
    QString toString();

    MessageType type = MessageType::none;
    int ContentLength = 0;
};

MessageHeader.cpp 文件:

MessageHeader::MessageHeader(QObject *parent)
    : QObject(parent)
{
}

MessageHeader::~MessageHeader()
{
}

MessageType MessageHeader::getType()
{
    return type;
}

int MessageHeader::getContentLength()
{
    return ContentLength;
}

void MessageHeader::setType(MessageType type)
{
    this->type = type;
}

void MessageHeader::setContentLength(int ContentLength)
{
    this->ContentLength = ContentLength;
}

QString MessageHeader::toString()
{
    return QString("NOT IMPLEMENTED YET");
}

反序列化函数模板助手:

  template<typename T>
    T* Deserialize(const QString &json)
    {
        bool status = false;

        QJson::Parser parser;
        QVariantMap map = parser.parse(json.toUtf8(), &status).toMap();

        if(!status)
            return NULL;

        T *obj = new T(); //don't worry about this, I'll rather take this from paramters once this is working
        QObject *p = (QObject *) obj; // cast done so that I see setProperty() method
        for(QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
        {
            const char *name = iter.key().toLatin1();
            const QVariant value = iter.value();
            qDebug() << "setting " << name << "=" << value;
            // the issue goes below. Here setProperty() return false.
            // At this point, name = 'type' and value = 2
            assert(p->setProperty(name, value));
        }
    //QJson::QObjectHelper::qvariant2qobject(map, obj);
    return obj;
}

上面函数的JSON输入字符串是这样的:

"{\"ContentLength\": 100, \"type\": 2}"

枚举类型在main功能之前注册:

qRegisterMetaType<MessageType>("MessageType");

这是本例中使用的QJson库。我使用此.pro文件

在Windows上构建它

编辑:

我刚发现indexOfProperty()

无法找到type属性
qDebug() << "id = " << meta->indexOfProperty(name); // print -1, name = 'type'

2 个答案:

答案 0 :(得分:1)

只有当变体类型为QStringQIntQUInt时,才能设置枚举属性here。因此,要成功设置枚举属性,变量必须是这些类型中的一种,而不是其他类型。 QJson将QULongLong解析为QInt的所有无符号整数。here, line 84。因此,一种方法是fork QJson并修改代码,以便将整数值转换为QUIntassert,或者将枚举值读/写为字符串。

另外,将语句放在qRegisterMetaType<MessageHeader::MessageType>("MessageType")内并不是一个好主意,但我认为你只是编写了试图解决问题的代码。

根据Qt文档,正如旁注,

  

[qRegisterMetaType]仅用于为每个其他用例注册别名(typedef)Q_DECLARE_METATYPE,而应使用qMetaTypeId()。

所以在标题中用Q_DECLARE_METATYPE(MessageHeader::MessageType)替换newOrderObject.ProductId = Product.Id return View(newOrderObject); 将是一个合理的举措。

答案 1 :(得分:1)

根据罗斯蒂斯拉夫的答案,如果您别无选择,只能收到QULongLong作为输入,下面是一个代码片段,如果要设置的属性是枚举,则可以将其转换:

#include <QMetaProperty>

const QMetaObject* meta = object->metaObject();
const int index = meta->indexOfProperty(propName);
if (index == -1) {/* report error*/}
if (meta->property(index).isEnumType())
    // special case for enums properties: they can be set from QInt or QUInt variants,
    // but unsigned integers parsed from json are QULongLong
    object->setProperty(propName, propVariant.value<unsigned int>());
else
    object->setProperty(propName, propVariant);