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?
-
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_OBJECTQ_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
@