JSON, Metatype, QVariant



  • Following problem, I use the JSON format to transfer the properties (defined by Q_PROPERTY) of an object to another computer.

    @Q_PROPERTY(quint8 byte READ getByte WRITE setByte NOTIFY byteChanged)@

    The problem is that quint8 is registers as QMetaType::UChar and in the JSON it is surrounded by ", which is not correct (the real value of byte is 42).

    @
    {
    "MPC1": {
    "byte": "*"
    } }
    @

    And later the value can't interpret:

    @
    2014-05-19 16:34 [0x02848f58] WARN MwDataBase - property 'byte' doesn't exists or can't convert from QString to char
    @

    What can I do, that the quint8 ist interpreted as number?


  • Lifetime Qt Champion

    Hi,

    Can you post a sample of code that reproduce this ?



  • Hi, no problem. I have created a compressed example. First the property class:

    @#ifndef MYPROPCLASS_H
    #define MYPROPCLASS_H

    #include <QObject>
    #include <QJsonDocument>
    #include <QJsonObject>

    class MyPropClass : public QObject
    {
    Q_OBJECT

    Q_PROPERTY(int value READ getValue WRITE setValue NOTIFY valueChanged)
    Q_PROPERTY(int value1 READ getValue1 WRITE setValue1 NOTIFY value1Changed)
    Q_PROPERTY(bool state READ getState WRITE setState NOTIFY stateChanged)
    Q_PROPERTY(Priority priority READ getPriority WRITE setPriority NOTIFY priorityChanged)
    Q_ENUMS(Priority)
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(quint8 byte READ getByte WRITE setByte NOTIFY byteChanged)
    Q_PROPERTY(quint16 word READ getWord WRITE setWord NOTIFY wordChanged)

    public:
    explicit MyPropClass(QObject *parentObj = 0);
    void getJsonObject(QJsonObject &jsonObj) const;
    void setJsonDocument(const QJsonDocument &jdoc);

    enum Priority { High, Low, VeryHigh, VeryLow };

    void setValue(int localParameter);
    void setValue1(int localParameter);
    void setState(bool localParameter);
    void setPriority(Priority localParameter);
    void setName(QString localParameter);
    void setByte(quint8 localParameter);
    void setWord(quint16 localParameter);

    int getValue() const { return value; }
    int getValue1() const {return value1; }
    bool getState() const { return state; }
    Priority getPriority() const {return priority; }
    QString getName() const { return name; }
    quint8 getByte() const { return byte; }
    quint16 getWord() const { return word; }

    signals:
    void valueChanged();
    void value1Changed();
    void stateChanged();
    void priorityChanged();
    void nameChanged();
    void byteChanged();
    void wordChanged();

    public slots:

    private:
    int value;
    int value1;
    bool state;
    Priority priority;
    QString name;
    quint8 byte;
    quint16 word;

    };

    #endif // MYPROPCLASS_H
    @

    Followed by the implementation including the Json methods.

    @#include "MyPropClass.h"

    #include <QDebug>
    #include <QMetaClassInfo>
    #include <QVariantMap>

    #define MWDATASETTER(varname)
    if (localParameter != varname)
    {
    varname = localParameter;
    emit varname ## Changed();
    }

    MyPropClass::MyPropClass(QObject *parentObj) :
    QObject(parentObj),
    value(876),
    value1(3782),
    state(true),
    priority(VeryLow),
    name("Steffen"),
    byte(42),
    word(8888)
    {
    }

    void MyPropClass::getJsonObject(QJsonObject &jsonObj) const
    {
    QVariantMap varMap;
    const QMetaObject *mo = this->metaObject();
    int count = mo->propertyCount();

    for (int i = 0; i < count; ++i)
    {
    QMetaProperty mp = mo->property(i);
    QString str = mp.name();
    qDebug() << "Property " << str << " Type: " << mp.typeName();

    varMap.insert(str, property(str.toLocal8Bit()));
    }
    varMap.remove("objectName");
    jsonObj[this->objectName()] = QJsonObject::fromVariantMap(varMap);

    }

    //! Convert the given JSON object to the property values of this
    //! object. For atomic datatypes the setProperty works fine. But we
    //! have problems to set a enum property. Thats the reason that we
    //! convert all numbers (QVariant::Double) to an integer if possible.
    void MyPropClass::setJsonDocument(const QJsonDocument &jdoc)
    {
    QJsonObject json = jdoc.object();

    for (QJsonObject::const_iterator itDoc = json.begin(); itDoc != json.end(); ++itDoc)
    {
    QVariantMap varMap = itDoc.value().toObject().toVariantMap();
    for (QVariantMap::const_iterator it = varMap.begin(); it != varMap.end(); ++it)
    {
    bool bRes = false;
    QVariant v = it.value();
    qDebug() << tr("read property %1 type: %2 value: ")
    .arg(it.key())
    .arg(v.typeName()) << v;

    if (QVariant::Double == v.type() && it.value().canConvert(QVariant::Int))
    {
    bRes = setProperty(it.key().toLocal8Bit(), v.toInt());
    }
    else
    {
    bRes = setProperty(it.key().toLocal8Bit(), v);
    }
    if (!bRes)
    {
    qDebug() << tr("ERR: property %1 doesn't exists or can't convert from %2 to %3")
    .arg(it.key())
    .arg(v.typeName())
    .arg(property(it.key().toLocal8Bit()).typeName());
    }
    }
    }
    }

    void MyPropClass::setValue(int localParameter)
    {
    MWDATASETTER(value)
    }

    void MyPropClass::setValue1(int localParameter)
    {
    MWDATASETTER(value1)
    }

    void MyPropClass::setState(bool localParameter)
    {
    MWDATASETTER(state)
    }

    void MyPropClass::setPriority(MyPropClass::Priority localParameter)
    {
    MWDATASETTER(priority)
    }

    void MyPropClass::setName(QString localParameter)
    {
    MWDATASETTER(name)
    }

    void MyPropClass::setByte(quint8 localParameter)
    {
    MWDATASETTER(byte)
    }

    void MyPropClass::setWord(quint16 localParameter)
    {
    MWDATASETTER(word)
    }
    @



  • And the main program to test something.

    @#include "MyPropClass.h"

    #include <QCoreApplication>
    #include <QDebug>
    #include <QJsonObject>
    #include <QJsonDocument>

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    MyPropClass *mpc1 = new MyPropClass();
    mpc1->setObjectName("MPC1");

    qDebug() << "---meta type information ------------";
    qDebug() << "quint8 : " << QMetaType::typeName(QMetaType::type("quint8"));
    qDebug() << "quint16: " << QMetaType::typeName(QMetaType::type("quint16"));

    qDebug() << "---startup value save to JSON------------";
    qDebug() << "value : " << mpc1->getValue();
    qDebug() << "value1 : " << mpc1->getValue1();
    qDebug() << "priority: " << mpc1->getPriority();
    qDebug() << "state : " << mpc1->getState();

    qDebug() << "---create JSON object -------------------";
    QJsonObject json;
    mpc1->getJsonObject(json);
    // create Document
    QJsonDocument jdoc;
    jdoc.setObject(json);
    qDebug() << jdoc.toJson(QJsonDocument::Indented);

    qDebug() << "---set some values-----------------------";
    mpc1->setProperty("value", 42);
    mpc1->setValue1(245);
    mpc1->setProperty("priority", "High"); // using a enum value
    mpc1->setProperty("priority", 1);
    mpc1->setByte(11);
    mpc1->setWord(1111);
    mpc1->setState(false);
    mpc1->setName("nobody");

    qDebug() << "value : " << mpc1->getValue();
    qDebug() << "value1 : " << mpc1->getValue1();
    qDebug() << "priority : " << mpc1->getPriority();
    qDebug() << "state : " << mpc1->getState();
    qDebug() << "byte : " << mpc1->getByte();
    qDebug() << "word : " << mpc1->getWord();
    qDebug() << "name : " << mpc1->getName();

    qDebug() << "---read saved values from JSON---------";
    mpc1->setJsonDocument(jdoc);

    qDebug() << "---show MPC1 resulting values --------------";
    qDebug() << "value : " << mpc1->getValue();
    qDebug() << "value1 : " << mpc1->getValue1();
    qDebug() << "priority: " << mpc1->getPriority();
    qDebug() << "state : " << mpc1->getState();
    qDebug() << "name : " << mpc1->getName();
    qDebug() << "byte : " << mpc1->getByte();
    qDebug() << "word : " << mpc1->getWord();

    return a.exec();
    }
    @

    My output is:
    @---meta type information ------------
    quint8 : uchar
    quint16: ushort
    ---startup value save to JSON------------
    value : 876
    value1 : 3782
    priority: 3
    state : true
    ---create JSON object -------------------
    Property "objectName" Type: QString
    Property "value" Type: int
    Property "value1" Type: int
    Property "state" Type: bool
    Property "priority" Type: Priority
    Property "name" Type: QString
    Property "byte" Type: uchar
    Property "word" Type: ushort
    "{
    "MPC1": {
    "byte": "",
    "name": "Steffen",
    "priority": 3,
    "state": true,
    "value": 876,
    "value1": 3782,
    "word": "8888"
    }
    }
    "
    ---set some values-----------------------
    value : 42
    value1 : 245
    priority : 1
    state : false
    byte : 11
    word : 1111
    name : "nobody"
    ---read saved values from JSON---------
    "read property byte type: QString value: " QVariant(QString, "
    ")
    "ERR: property byte doesn't exists or can't convert from QString to uchar"
    "read property name type: QString value: " QVariant(QString, "Steffen")
    "read property priority type: double value: " QVariant(double, 3)
    "read property state type: bool value: " QVariant(bool, true)
    "read property value type: double value: " QVariant(double, 876)
    "read property value1 type: double value: " QVariant(double, 3782)
    "read property word type: QString value: " QVariant(QString, "8888")
    ---show MPC1 resulting values --------------
    value : 876
    value1 : 3782
    priority: 3
    state : true
    name : "Steffen"
    byte : 11
    word : 8888
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.