添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

开发项目中最重要的组成部分非数据莫属了,这里介绍一种QT项目中的数据封装方法。方法中封装的数据能进行自我监测,发生变化之后主动向外部发送消息通知变化,同时封装的数据可以实现与JSON数据结构之间的相互转换,这对于数据持久化和网络请求是很有帮助的。

基本类型封装

为了提升代码的复用性,这里我们将通用的方法和属性与基本的属性类型封装到一起,方便程序的调用。基本类型之间的继承关系如下图所示:

DatabDecorator 是数据封装的基类,包含了数据内容的一些通用属性
StringDecorator 是对字符串类型的属性的封装
IntDecorator 是对整型类型的属性的封装
EnumeratorDecorator 是对枚举类型的数据的封装
DateTimeDecorator 是对日期类型的数据的封装

基本类型的数据基类如下,封装了属性字段需要的额外的辅助参数,以及与Json结构之间相互转化的方法接口

1、datadecorator.h

#ifndef DATADECORATOR_H
#define DATADECORATOR_H
#include <QJsonObject>
#include <QJsonValue>
#include <QObject>
#include <QScopedPointer>
class Entity;
class DataDecorator : public QObject
    Q_OBJECT
    //导出QML中需要访问属性
    Q_PROPERTY( QString ui_describe READ label CONSTANT )
public:
    /**@brief 构造描述
   * @1 该属性字段属于哪个数据实体
   * @2 该属性字段对应的key值
   * @3 该属性字段对应的描述信息
    DataDecorator(Entity* parent = nullptr, const QString& key = "SomeItemKey", const QString& label = "");
    virtual ~DataDecorator();
    const QString& key() const;   //key值用来查找该属性
    const QString& label() const; //label用来描述该属性字段
    Entity* parentEntity();       //属性字段属于哪个数据实体(比如用户等)
    //Json和数据类之间的相互转化
    virtual QJsonValue jsonValue() const = 0;
    virtual void update(const QJsonObject& jsonObject) = 0;
private:
    //私有的数据类
    class Implementation;
    QScopedPointer<Implementation> implementation;
#endif

2、datadecorator.cpp

#include "data-decorator.h"
class DataDecorator::Implementation
public:
    Implementation(Entity* _parent, const QString& _key, const QString& _label)
        : parentEntity(_parent)
        , key(_key)
        , label(_label)
    Entity* parentEntity{nullptr};
    QString key;
    QString label;
DataDecorator::DataDecorator(Entity* parent, const QString& key, const QString& label)
    : QObject((QObject*)parent)
    implementation.reset(new Implementation(parent, key, label));
DataDecorator::~DataDecorator()
const QString& DataDecorator::key() const
    return implementation->key;
const QString& DataDecorator::label() const
    return implementation->label;
Entity* DataDecorator::parentEntity()
    return implementation->parentEntity;

基本类型的封装类派生自DataDecorator类,实现如下:

1.对字符串类型的封装

1、stringdecorator.h

#ifndef STRINGDECORATOR_H
#define STRINGDECORATOR_H
#include <QJsonObject>
#include <QJsonValue>
#include <QObject>
#include <QScopedPointer>
#include <QString>
#include <data/data-decorator.h>
class  StringDecorator : public DataDecorator
    Q_OBJECT
   //QML访问的属性
    Q_PROPERTY( QString ui_value READ value WRITE setValue NOTIFY valueChanged )
public:
    StringDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", const QString& value = "");
    ~StringDecorator();
    //修改和获取字符串封装类型中的原始数据
    StringDecorator& setValue(const QString& value);
    const QString& value() const;
    QJsonValue jsonValue() const override;
    void update(const QJsonObject& jsonObject) override;
signals:
    //数据发生变化的时候发送的信号
    void valueChanged();
private:
    class Implementation;
    QScopedPointer<Implementation> implementation;
#endif

2、stringdecorator.cpp

#include "string-decorator.h"
#include <QVariant>
class StringDecorator::Implementation
public:
    Implementation(StringDecorator* _stringDecorator, const QString& _value)
        : stringDecorator(_stringDecorator)
        , value(_value)
    StringDecorator* stringDecorator{nullptr};
    QString value;
StringDecorator::




    
StringDecorator(Entity* parentEntity, const QString& key, const QString& label, const QString& value)
    : DataDecorator(parentEntity, key, label)
    implementation.reset(new Implementation(this, value));
StringDecorator::~StringDecorator()
const QString& StringDecorator::value() const
    return implementation->value;
StringDecorator& StringDecorator::setValue(const QString& value)
    if(value != implementation->value) {
        implementation->value = value;
        emit valueChanged();
    return *this;
QJsonValue StringDecorator::jsonValue() const
    return QJsonValue::fromVariant(QVariant(implementation->value));
void StringDecorator::update(const QJsonObject& _jsonObject)
    if (_jsonObject.contains(key())) {
        setValue(_jsonObject.value(key()).toString());
2.对整型的封装

1、intdecorator.h

#ifndef INTDECORATOR_H
#define INTDECORATOR_H
#include <QJsonObject>
#include <QJsonValue>
#include <QObject>
#include <QScopedPointer>
#include <data/data-decorator.h>
class  IntDecorator : public DataDecorator
    Q_OBJECT
   // QML访问的接口
    Q_PROPERTY( int ui_value READ value WRITE setValue NOTIFY valueChanged )
public:
    IntDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", int value = 0);
    ~IntDecorator();
    //修改和获取对应的属性值
    IntDecorator& setValue(int value);
    int value() const;
public:
    QJsonValue jsonValue() const override;
    void update(const QJsonObject& jsonObject) override;
signals:
    void valueChanged();
private:
    class Implementation;
    QScopedPointer<Implementation> implementation;
#endif

2、intdecorator.cpp

#include "int-decorator.h"
#include <QVariant>
class IntDecorator::Implementation
public:
    Implementation(IntDecorator* intDecorator, int value)
        : intDecorator(intDecorator)
        , value(value)
    IntDecorator* intDecorator{nullptr};
    int value;
IntDecorator::IntDecorator(Entity* parentEntity, const QString& key, const QString& label, int value)
    : DataDecorator(parentEntity, key, label)
    implementation.reset(new Implementation(this, value));
IntDecorator::~IntDecorator()
int IntDecorator::value() const
    return implementation->value;
IntDecorator& IntDecorator::setValue(int value)
    if(value != implementation->value) {
        // ...Validation here if required...
        implementation->value = value;
        emit valueChanged();
    return *this;
QJsonValue IntDecorator::jsonValue() const
    return QJsonValue::fromVariant(QVariant(implementation->value));
void IntDecorator::update(const QJsonObject& jsonObject)
    if (jsonObject.contains(key())) {
        auto l_value = jsonObject.value(key()).toInt();
        setValue(l_value);
    } else {
        setValue(0);
3.对枚举类型进行封装

和其它的基本类型不同,枚举类型除了包含一个整型的数值以外,还包含一个映射表,对每个枚举数值有一个对应的字符串映射,用于枚举的对外显示。

1、enumeratordecorator.h

#ifndef ENUMERATORDECORATOR_H
#define ENUMERATORDECORATOR_H
#include <map>
#include <QJsonObject>
#include <QJsonValue>
#include <QObject>
#include <QScopedPointer>
#include <data/data-decorator.h>
class EnumeratorDecorator : public DataDecorator
    Q_OBJECT
    //枚举属性值
    Q_PROPERTY( int ui_value READ value WRITE setValue NOTIFY valueChanged )
    //枚举属性对应的字符串描述
    Q_PROPERTY( QString ui_valueDescription READ valueDescription NOTIFY valueChanged )
public:
    EnumeratorDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", int value = 0, const std::map<int, QString>& descriptionMapper = std::map<int, QString>());
    ~EnumeratorDecorator();
    //获取属性对应的值和描述
    EnumeratorDecorator& setValue(int value);
    int value() const;
    QString valueDescription() const;
    QJsonValue jsonValue() const override;
    void update(const QJsonObject& jsonObject) override;
signals:
    void valueChanged();
private:
    class Implementation;
    QScopedPointer<Implementation> implementation;
#endif

2、enumeratordecorator.cpp

#include "enumerator-decorator.h"
#include <QVariant>
class EnumeratorDecorator::Implementation
public:
    Implementation(EnumeratorDecorator* enumeratorDecorator, int value, const std::map<int, QString>& descriptionMapper)
        : enumeratorDecorator(enumeratorDecorator)
        , value(value)
        , descriptionMapper(descriptionMapper)
    EnumeratorDecorator* enumeratorDecorator{nullptr};
    int value;
    std::map<int, QString> descriptionMapper;
EnumeratorDecorator::EnumeratorDecorator(Entity* parentEntity, const QString& key, const QString& label, int value, const std::map<int, QString>& descriptionMapper)
    : DataDecorator(parentEntity, key, label)
    implementation.reset(new Implementation(this, value, descriptionMapper));
EnumeratorDecorator::~EnumeratorDecorator()
int EnumeratorDecorator::value() const
    return implementation->value;
QString EnumeratorDecorator::valueDescription() const
    if (implementation->descriptionMapper.find(implementation->value) != implementation->descriptionMapper.end()) {
        return implementation->descriptionMapper.at(implementation->value);
    } else {
        return {};
EnumeratorDecorator& EnumeratorDecorator::setValue(int value)
    if (value != implementation->value) {
        // ...Validation here if required...
        implementation->value = value;
        emit valueChanged();
    return *this;
QJsonValue EnumeratorDecorator::jsonValue() const
    return QJsonValue::fromVariant(QVariant(implementation->value));
void EnumeratorDecorator::update(const QJsonObject& jsonObject)
    if (jsonObject.contains(key())) {
        auto valueFromJson = jsonObject.value(key()).toInt();
        setValue(valueFromJson);
    } else {
        setValue(0);
4.对日期类型进行封装

由于日期有不同的显示形式,因此我们在日期的封装类型中扩展一些新的接口,方便调用者获取日期的不同显示形式。

1、datetimedecorator.h

#ifndef DATETIMEDECORATOR_H
#define DATETIMEDECORATOR_H
#include <QDateTime>
#include <QJsonObject>
#include <QJsonValue>




    

#include <QObject>
#include <QScopedPointer>
#include <data/data-decorator.h>
class DateTimeDecorator : public DataDecorator
    Q_OBJECT
    //QML中访问各种日期的格式
    Q_PROPERTY( QString ui_iso8601String READ toIso8601String NOTIFY valueChanged )
    Q_PROPERTY( QString ui_prettyDateString READ toPrettyDateString NOTIFY valueChanged )
    Q_PROPERTY( QString ui_prettyTimeString READ toPrettyTimeString NOTIFY valueChanged )
    Q_PROPERTY( QString ui_prettyString READ toPrettyString NOTIFY valueChanged )
    Q_PROPERTY( QDateTime ui_value READ value WRITE setValue NOTIFY valueChanged )
public:
    DateTimeDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", const QDateTime& value = QDateTime());
    ~DateTimeDecorator();
    const QDateTime& value() const;
    DateTimeDecorator& setValue(const QDateTime& value);
    //获取各种显示格式
    QString toIso8601String() const;
    QString toPrettyDateString() const;
    QString toPrettyTimeString() const;
    QString toPrettyString() const;
    QJsonValue jsonValue() const override;
    void update(const QJsonObject& jsonObject) override;
signals:
    void valueChanged();
private:
    class Implementation;
    QScopedPointer<Implementation> implementation;
#endif

2、datetimedecorator.cpp

#include "datetime-decorator.h"
#include <QVariant>
class DateTimeDecorator::Implementation
public:
    Implementation(DateTimeDecorator* dateTimeDecorator, const QDateTime& value)
        : dateTimeDecorator(dateTimeDecorator)
        , value(value)
    DateTimeDecorator* dateTimeDecorator{nullptr};
    QDateTime value;
DateTimeDecorator::DateTimeDecorator(Entity* parentEntity, const QString& key, const QString& label, const QDateTime& value)
    : DataDecorator(parentEntity, key, label)
    implementation.reset(new Implementation(this, value));
DateTimeDecorator::~DateTimeDecorator()
const QDateTime& DateTimeDecorator::value() const
    return implementation->value;
DateTimeDecorator& DateTimeDecorator::setValue(const QDateTime& value)
    if(value != implementation->value) {
        // ...Validation here if required...
        implementation->value = value;
        emit valueChanged();
    return *this;
QString DateTimeDecorator::toIso8601String() const
    if (implementation->value.isNull()) {
        return "";
    } else {
        return implementation->value.toString(Qt::ISODate);
QString DateTimeDecorator::toPrettyString() const
    if (implementation->value.isNull()) {
        return "Not set";
    } else {
        return implementation->value.toString( "ddd d MMM yyyy @ HH:mm:ss" );
QString DateTimeDecorator::toPrettyDateString() const
    if (implementation->value.isNull()) {
        return "Not set";
    } else {
        return implementation->value.toString( "d MMM yyyy" );
QString DateTimeDecorator::toPrettyTimeString() const
    if (implementation->value.isNull()) {
        return "Not set";
    } else {
        return implementation->value.toString( "hh:mm ap" );
QJsonValue DateTimeDecorator::jsonValue() const
    return QJsonValue::fromVariant(QVariant(implementation->value.toString(Qt::ISODate)));
void DateTimeDecorator::update(const QJsonObject& jsonObject)
    if (jsonObject.contains(key())) {
        auto valueAsString = jsonObject.




    
value(key()).toString();
        auto valueAsDate = QDateTime::fromString(valueAsString, Qt::ISODate);  // yyyy-MM-ddTHH:mm:ss
        setValue(valueAsDate);
    } else {
        setValue(QDateTime());

数据信息类封装

封装好了基本类型就可以进一步封装数据信息类了。数据信息类就是一个有很多基本类型组合成的一个有机的数据集合整体,基本数据之间都是有逻辑关系的。比如消费者信息类就包含:字符串类型的姓名、整型的年龄、字符串类型的地址、字符串类型的性别等等。数据信息类和基本类型之间的对应关系有一对一的,也有一对多的,比如一个人只有一个名字,但可能有多个地址,在封装的时候需要考虑到这点。数据信息类的封装类之间的关系如下图所示:
在这里插入图片描述
数据实体的基类Entity封装实体需要基本属性和方法,一个数据实体包含多个基本类型的属性。同时一个数据实体可能包含多个其它的数据实体,比如一个用户可以拥有多量车多个账户等等。

1.数据信息体封装

Entity包含数据信息实体的基本属性和方法实现如下:

1、entity.h

#ifndef ENTITY_H
#define ENTITY_H
#include <map>
#include <QObject>
#include <QScopedPointer>
#include <data/data-decorator.h>
#include <data/entity-collection.h>
class Entity : public QObject
    Q_OBJECT
public:
    Entity(QObject* parent = nullptr, const QString& key = "SomeEntityKey");
    Entity(QObject* parent, const QString& key, const QJsonObject& jsonObject);
    virtual ~Entity();
public:
    //数据信息体对应的key值
    const QString& key() const;
    //数据信息类和Json结构之间的相互转换
    void update(const QJsonObject& jsonObject);
    QJsonObject toJson() const;
signals:
    //信息体集合发生变化
    void childCollectionsChanged(const QString& collectionKey);
    //包含的信息体发生变化
    void childEntitiesChanged();
    //包含的属性发生变化
    void dataDecoratorsChanged();
protected:
    //添加包含的信信息体
    Entity* addChild(Entity* entity, const QString& key);
    //添加包含的信息实体列表
    EntityCollectionBase* addChildCollection(EntityCollectionBase* entityCollection);
    //添加子属性
    DataDecorator* addDataItem(DataDecorator* dataDecorator);
protected:
    class Implementation;
    QScopedPointer<Implementation> implementation;
#endif

2、entity.cpp

#include "entity.h"
#include <QJsonArray>
class Entity::Implementation
public:
    Implementation(Entity* _entity, const QString& _key)
        : entity(_entity)
        , key(_key)
    Entity* entity{nullptr};
    QString key;
    std::map<QString, EntityCollectionBase*> childCollections;
    std::map<QString, Entity*> childEntities;
    std::map<QString, DataDecorator*> dataDecorators;
Entity::Entity(QObject* parent, const QString& key)
    : QObject(parent)
    implementation.reset(new Implementation(this, key));
Entity::Entity(QObject* parent, const QString& key, const QJsonObject& jsonObject)
    : Entity(parent, key)
    update(jsonObject);
Entity::~Entity()
const QString& Entity::key() const
    return implementation->key;
Entity* Entity::addChild(Entity* entity, const QString& key)
    if(implementation->childEntities.find(key) == std::end(implementation->childEntities)) {
        implementation->childEntities[key] = entity;
        emit childEntitiesChanged();
    return entity;
EntityCollectionBase* Entity::addChildCollection(EntityCollectionBase* entityCollection)
    if(implementation->childCollections.find(entityCollection->getKey()) == std::end(implementation->childCollections)) {
        implementation->childCollections[entityCollection->getKey()] = entityCollection;
        emit childCollectionsChanged(entityCollection->getKey());
    return entityCollection;
DataDecorator* Entity::addDataItem(DataDecorator* dataDecorator)
    if(implementation->dataDecorators.find(dataDecorator->




    
key()) == std::end(implementation->dataDecorators)) {
        implementation->dataDecorators[dataDecorator->key()] = dataDecorator;
        emit dataDecoratorsChanged();
    return dataDecorator;
void Entity::update(const QJsonObject& jsonObject)
    // Update data decorators
    for (std::pair<QString, DataDecorator*> dataDecoratorPair : implementation->dataDecorators) {
        dataDecoratorPair.second->update(jsonObject);
    // Update child entities
    for (std::pair<QString, Entity*> childEntityPair : implementation->childEntities) {
        childEntityPair.second->update(jsonObject.value(childEntityPair.first).toObject());
    // Update child collections
    for (std::pair<QString, EntityCollectionBase*> childCollectionPair : implementation->childCollections) {
        childCollectionPair.second->update(jsonObject.value(childCollectionPair.first).toArray());
QJsonObject Entity::toJson() const
    QJsonObject returnValue;
    // Add data decorators
    for (std::pair<QString, DataDecorator*> dataDecoratorPair : implementation->dataDecorators) {
        returnValue.insert( dataDecoratorPair.first, dataDecoratorPair.second->jsonValue() );
    // Add child entities
    for (std::pair<QString, Entity*> childEntityPair : implementation->childEntities) {
        returnValue.insert( childEntityPair.first, childEntityPair.second->toJson() );
    // Add child collections
    for (std::pair<QString, EntityCollectionBase*> childCollectionPair : implementation->childCollections) {
        QJsonArray entityArray;
            for (Entity* entity : childCollectionPair.second->baseEntities()) {
            entityArray.append( entity->toJson() );
        returnValue.insert( childCollectionPair.first, entityArray );
    return returnValue;
2.数据信息集合封装

数据信息集合就是对数据体的列表进行封装,比如一个用户包含一个地址列表,地址列表就是地址信息的集合。通过模板操作,我们可以实现各种信息实体的序列化和反序列化,信息集合的实现如下:

#ifndef ENTITYCOLLECTION_H
#define ENTITYCOLLECTION_H
#include <QJsonArray>
#include <QJsonValue>
#include <QObject>
class Entity;
//基类声明集合变化的信号
class EntityCollectionObject : public QObject
    Q_OBJECT
public:
    EntityCollectionObject(QObject* _parent = nullptr) : QObject(_parent) {}
    virtual ~EntityCollectionObject() {}
signals:
    void collectionChanged();
//数据信息集合的基类
class EntityCollectionBase : public EntityCollectionObject
public:
    EntityCollectionBase(QObject* parent = nullptr, const QString& key = "SomeCollectionKey")
        : EntityCollectionObject(parent)
        , key(key)
    virtual ~EntityCollectionBase()
    QString getKey() const
        return key;
    virtual void clear() = 0;
    //json数组转成数据实体
    virtual void update(const QJsonArray& json) = 0;
    virtual std::vector<Entity*> baseEntities() = 0;
    template <class T>
    QList<T*>& derivedEntities();
    template <class T>
    T* addEntity(T* entity);
private:
    QString key;
//数据信息基类
template <typename T>
class EntityCollection : public EntityCollectionBase
public:
    EntityCollection(QObject* parent = nullptr, const QString& key = "SomeCollectionKey")
        : EntityCollectionBase(parent, key)
    ~EntityCollection()
    //清空列表
    void clear() override
        for(auto entity : collection) {
            entity->deleteLater




    
();
        collection.clear();
    //更新列表
    void update(const QJsonArray& jsonArray) override
        clear();
        for(const QJsonValue& jsonValue : jsonArray) {
            addEntity(new T(this, jsonValue.toObject()));
    //获取列表
    std::vector<Entity*> baseEntities() override
        std::vector<Entity*> returnValue;
        for(T* entity : collection) {
            returnValue.push_back(entity);
        return returnValue;
    //获取列表的引用
    QList<T*>& derivedEntities()
        return collection;
    //添加新的信息实体
    T* addEntity(T* entity)
        if(!collection.contains(entity)) {
            collection.append(entity);
            EntityCollectionObject::collectionChanged();
        return entity;
private:
    QList<T*> collection;
template <class T>
QList<T*>& EntityCollectionBase::derivedEntities()
    return dynamic_cast<const EntityCollection<T>&>(*this).derivedEntities();
template <class T>
T* EntityCollectionBase::addEntity(T* entity)
    return dynamic_cast<const EntityCollection<T>&>(*this).addEntity(entity);
#endif

使用封装的数据结构

1.定义新的业务数据类型

封装完成之后,我们就可以在项目中使用我们封装的类型了,这里以一个消费者Customer为例说明一下封装的基本类型的使用方法。Customer消费者包含两个基本属性字符串类型的姓名,整型的年龄,以及一个地址列表。地址包含城市街道邮政编码等信息,地址的实现方式如下:
1、address.h

#ifndef ADDRESS_H
#define ADDRESS_H
#include <QObject>
#include <data/string-decorator.h>
#include <data/entity.h>
class Address : public Entity
    Q_OBJECT
    Q_PROPERTY(StringDecorator* ui_building MEMBER building CONSTANT)
    Q_PROPERTY(StringDecorator* ui_street MEMBER street CONSTANT)
    Q_PROPERTY(StringDecorator* ui_city MEMBER city CONSTANT)
    Q_PROPERTY(StringDecorator* ui_postcode MEMBER postcode CONSTANT)
    Q_PROPERTY(QString ui_fullAddress READ fullAddress CONSTANT)
public:
    explicit Address(QObject* parent = nullptr);
    Address(QObject* parent, const QJsonObject& json);
    StringDecorator* building{nullptr}; //建筑
    StringDecorator* street{nullptr};   //街道
    StringDecorator* city{nullptr};     //城市
    StringDecorator* postcode{nullptr}; //邮政编码
    QString fullAddress() const;
#endif

2、address.cpp

#include "address.h"
Address::Address(QObject* parent)
        : Entity(parent, "address")
    building = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "building", "Building")));
    street = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "street", "Street")));
    city = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "city", "City")));
    postcode = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "postcode", "Post Code")));
Address::Address(QObject* parent, const QJsonObject& json)
        : Address(parent)
    update(json);
QString Address::fullAddress() const
    return building->value() + " " + street->




    
value() + "\n" + city->value() + "\n" + postcode->value();
消费者信息类中除了包含基本属性之外,还包含一个地址信息集合,对应的实现如下:

1、customer.h

#ifndef Customer_H
#define Customer_H
#include <QObject>
#include <QtQml/QQmlListProperty>
#include <data/string-decorator.h>
#include <data/int-decorator.h>
#include <data/entity.h>
#include <data/entity-collection.h>
#include <data/address.h>
class Customer : public Entity
    Q_OBJECT
    //QML访问的信息接口
    //年龄信息
    Q_PROPERTY( IntDecorator* ui_age MEMBER age CONSTANT )
    //姓名信息
    Q_PROPERTY( StringDecorator* ui_name MEMBER name CONSTANT )
    Q_PROPERTY( Address* ui_mainAddress MEMBER defaultAddr CONSTANT ) //默认地址
    //地址列表
    Q_PROPERTY( QQmlListProperty<Address> ui_address READ ui_address NOTIFY addresssListChanged)
public:
    explicit Customer(QObject* parent = nullptr);
    Customer(QObject* parent, const QJsonObject& json);
    IntDecorator* age{nullptr};       //年龄
    StringDecorator* name{nullptr};   //姓名
    Address* defaultAddr{nullptr};    //默认地址
    //地址列表
    EntityCollection<Address>* addresses{nullptr};
    //qml访问的地址列表
    QQmlListProperty<Address> ui_address();
signals:
    void addresssListChanged();
#endif

2、customer.cpp

#include "customer.h"
Customer::Customer(QObject* parent)
    : Entity(parent, "Customer")
    age = static_cast<IntDecorator*>(addDataItem(new IntDecorator(this, "age", "年龄")));
    name = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "name", "姓名")));
    defaultAddr = static_cast<Address*>(addChild(new Address(this), "defaultAddress"));
    addresses = static_cast<EntityCollection<Address>*>(addChildCollection(new EntityCollection<Address>(this, "address")));
Customer::Customer(QObject* parent, const QJsonObject& json)
    : Customer(parent)
    update(json);
QQmlListProperty<Address> Customer::ui_address()
    return QQmlListProperty<Address>(this, addresses->derivedEntities());
2.使用新的数据类型

通过使用新的封装类型,我们就可以实现Json结构和数据类之间的相互转换了,使用方法如下:

#include "widget.h"
#include <QApplication>
#include <data/customer.h>
#include <data/address.h>
int main(int argc, char *argv[])
    QApplication a(argc, argv);
    //将json结构转换成一个数据类
    QJsonObject customer_json;
    Customer* customer = new Customer(NULL,customer_json);
    //名字变化处理
    QObject::connect(customer->name,&StringDecorator::valueChanged,[&](){});
    //年龄变化的处理
    QObject::connect(customer->age,&IntDecorator::valueChanged,[&](){});
    //默认地址变化的处理
    QObject::connect(customer->defaultAddr,&Address::dataDecoratorsChanged,[&](){});
    //修改数据
    customer->name->setValue("小明");
    customer->age->setValue(23);
    customer->defaultAddr->city->setValue("北京市");
    customer->defaultAddr->street->setValue("光明街道");
    customer->defaultAddr->building->setValue("6号楼");
    customer->defaultAddr->postcode->setValue("56788");
    //添加新地址
    Address* new_addr = new Address();
    new_addr->city->setValue("西河市");
    new_addr->street->setValue("细节街道");
    new_addr->building->setValue("6号楼");
    new_addr->postcode->setValue("56789");
    customer->addresses->addEntity(new_addr);
    //将数据类型转换成json数据结构
    QJsonObject json_object = customer->toJson();
    return a.exec();

通过这种封装,我们就可以实现数据类和Json数据结构之间的相互转化了,同时所有属性都有描述信息,这对于我们的复用和扩展都是很有帮助的。

void Client::StructToJSon(const std::vector<sDefectItem>& vecDefect, QByteArray &jsonArray) for(int i = 0; i < vecDefect.size(); i++) QJsonObject rootObj, objStat...
QJsonDoucument 它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取写入该文档。 QJsonArray JSON 数组是一个值列表。可以通过从数组中插入删除 QJsonValue 来操作该列表。 QJsonObject JSON 对象是键值对的列表,其中键是唯一的字符串,值由 QJs
自己根据CMarkup启发,使用QJsonDocument完成类似CMarkup调用的json组装解析实例,内测多次无问题,目前还有优化空间,我的环境是qt5.5,欢迎大家提出不同意见共同进步。 本实例使用数据为测试数据,实际数据可根据业务需求进行扩展。
由于json格式的数据阅读起来简单方便,也便于机器解析与生成。在最近的项目中,使用json格式的数据可以快速的传输,首次使用这种格式,所以把自己的封装数组的使用心得记录下来。         QJsonObject json;         QJsonArray   Array;    json.insert("x","100");     json.insert("y","200"...
之前貌似没有看过类似的代码 我们现在的要求就是直接在不知道类成员的情况下,把一个类丢进去就能生成一个Json字符串,也可以把一个字符串一个类成员丢进去就能根据成员变量名匹配到元素并赋值,大概就这样 中心思想就是Q_PROPERTY宏提供了一个property类型,可以直接通过变量名称获得一个变量名称对应的字符串,比如int a;可以直接获得一个"a"的字符串,而且还可以知道这个a 的类型。并据...