• QT项目中通过数据封装实现Json结构和数据类之间的相互转换


    目录

    基本类型封装

    1.对字符串类型的封装

    2.对整型的封装

    3.对枚举类型进行封装

    3.对日期类型进行封装

    数据信息类封装

    1.数据信息体封装

    2.数据信息集合封装

    使用封装的数据结构

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

    2.使用新的数据类型

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

    基本类型封装

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

    DataDecorator是数据封装的基类,包含了数据内容的一些通用属性

    StringDecorator是对字符串类型的属性的封装

    IntDecorator是对整型类型的属性的封装

    EnumeratorDecorator是对枚举类型的数据的封装

    DateTimeDecorator是对日期类型的数据的封装

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

    1. //data-decorator.h
    2. #ifndef DATADECORATOR_H
    3. #define DATADECORATOR_H
    4. #include <QJsonObject>
    5. #include <QJsonValue>
    6. #include <QObject>
    7. #include <QScopedPointer>
    8. class Entity;
    9. class DataDecorator : public QObject
    10. {
    11. Q_OBJECT
    12. //导出QML中需要访问属性
    13. Q_PROPERTY( QString ui_describe READ label CONSTANT )
    14. public:
    15. /**@brief 构造描述
    16. * @1 该属性字段属于哪个数据实体
    17. * @2 该属性字段对应的key值
    18. * @3 该属性字段对应的描述信息
    19. */
    20. DataDecorator(Entity* parent = nullptr, const QString& key = "SomeItemKey", const QString& label = "");
    21. virtual ~DataDecorator();
    22. const QString& key() const; //key值用来查找该属性
    23. const QString& label() const; //label用来描述该属性字段
    24. Entity* parentEntity(); //属性字段属于哪个数据实体(比如用户等)
    25. //Json和数据类之间的相互转化
    26. virtual QJsonValue jsonValue() const = 0;
    27. virtual void update(const QJsonObject& jsonObject) = 0;
    28. private:
    29. //私有的数据类
    30. class Implementation;
    31. QScopedPointer<Implementation> implementation;
    32. };
    33. #endif

    1. //data-decorator.cpp
    2. #include "data-decorator.h"
    3. class DataDecorator::Implementation
    4. {
    5. public:
    6. Implementation(Entity* _parent, const QString& _key, const QString& _label)
    7. : parentEntity(_parent)
    8. , key(_key)
    9. , label(_label)
    10. {
    11. }
    12. Entity* parentEntity{nullptr};
    13. QString key;
    14. QString label;
    15. };
    16. DataDecorator::DataDecorator(Entity* parent, const QString& key, const QString& label)
    17. : QObject((QObject*)parent)
    18. {
    19. implementation.reset(new Implementation(parent, key, label));
    20. }
    21. DataDecorator::~DataDecorator()
    22. {
    23. }
    24. const QString& DataDecorator::key() const
    25. {
    26. return implementation->key;
    27. }
    28. const QString& DataDecorator::label() const
    29. {
    30. return implementation->label;
    31. }
    32. Entity* DataDecorator::parentEntity()
    33. {
    34. return implementation->parentEntity;
    35. }

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

    1.对字符串类型的封装

    1. //string-decorator.h
    2. #ifndef STRINGDECORATOR_H
    3. #define STRINGDECORATOR_H
    4. #include <QJsonObject>
    5. #include <QJsonValue>
    6. #include <QObject>
    7. #include <QScopedPointer>
    8. #include <QString>
    9. #include <data/data-decorator.h>
    10. class StringDecorator : public DataDecorator
    11. {
    12. Q_OBJECT
    13. //QML访问的属性
    14. Q_PROPERTY( QString ui_value READ value WRITE setValue NOTIFY valueChanged )
    15. public:
    16. StringDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", const QString& value = "");
    17. ~StringDecorator();
    18. //修改和获取字符串封装类型中的原始数据
    19. StringDecorator& setValue(const QString& value);
    20. const QString& value() const;
    21. QJsonValue jsonValue() const override;
    22. void update(const QJsonObject& jsonObject) override;
    23. signals:
    24. //数据发生变化的时候发送的信号
    25. void valueChanged();
    26. private:
    27. class Implementation;
    28. QScopedPointer<Implementation> implementation;
    29. };
    30. #endif

    1. //string-decorator.cpp
    2. #include "string-decorator.h"
    3. #include <QVariant>
    4. class StringDecorator::Implementation
    5. {
    6. public:
    7. Implementation(StringDecorator* _stringDecorator, const QString& _value)
    8. : stringDecorator(_stringDecorator)
    9. , value(_value)
    10. {
    11. }
    12. StringDecorator* stringDecorator{nullptr};
    13. QString value;
    14. };
    15. StringDecorator::StringDecorator(Entity* parentEntity, const QString& key, const QString& label, const QString& value)
    16. : DataDecorator(parentEntity, key, label)
    17. {
    18. implementation.reset(new Implementation(this, value));
    19. }
    20. StringDecorator::~StringDecorator()
    21. {
    22. }
    23. const QString& StringDecorator::value() const
    24. {
    25. return implementation->value;
    26. }
    27. StringDecorator& StringDecorator::setValue(const QString& value)
    28. {
    29. if(value != implementation->value) {
    30. implementation->value = value;
    31. emit valueChanged();
    32. }
    33. return *this;
    34. }
    35. QJsonValue StringDecorator::jsonValue() const
    36. {
    37. return QJsonValue::fromVariant(QVariant(implementation->value));
    38. }
    39. void StringDecorator::update(const QJsonObject& _jsonObject)
    40. {
    41. if (_jsonObject.contains(key())) {
    42. setValue(_jsonObject.value(key()).toString());
    43. }
    44. }

    2.对整型的封装

    1. //int-decorator.h
    2. #ifndef INTDECORATOR_H
    3. #define INTDECORATOR_H
    4. #include <QJsonObject>
    5. #include <QJsonValue>
    6. #include <QObject>
    7. #include <QScopedPointer>
    8. #include <data/data-decorator.h>
    9. class IntDecorator : public DataDecorator
    10. {
    11. Q_OBJECT
    12. // QML访问的接口
    13. Q_PROPERTY( int ui_value READ value WRITE setValue NOTIFY valueChanged )
    14. public:
    15. IntDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", int value = 0);
    16. ~IntDecorator();
    17. //修改和获取对应的属性值
    18. IntDecorator& setValue(int value);
    19. int value() const;
    20. public:
    21. QJsonValue jsonValue() const override;
    22. void update(const QJsonObject& jsonObject) override;
    23. signals:
    24. void valueChanged();
    25. private:
    26. class Implementation;
    27. QScopedPointer<Implementation> implementation;
    28. };
    29. #endif

    1. //int-decorator.cpp
    2. #include "int-decorator.h"
    3. #include <QVariant>
    4. class IntDecorator::Implementation
    5. {
    6. public:
    7. Implementation(IntDecorator* intDecorator, int value)
    8. : intDecorator(intDecorator)
    9. , value(value)
    10. {
    11. }
    12. IntDecorator* intDecorator{nullptr};
    13. int value;
    14. };
    15. IntDecorator::IntDecorator(Entity* parentEntity, const QString& key, const QString& label, int value)
    16. : DataDecorator(parentEntity, key, label)
    17. {
    18. implementation.reset(new Implementation(this, value));
    19. }
    20. IntDecorator::~IntDecorator()
    21. {
    22. }
    23. int IntDecorator::value() const
    24. {
    25. return implementation->value;
    26. }
    27. IntDecorator& IntDecorator::setValue(int value)
    28. {
    29. if(value != implementation->value) {
    30. // ...Validation here if required...
    31. implementation->value = value;
    32. emit valueChanged();
    33. }
    34. return *this;
    35. }
    36. QJsonValue IntDecorator::jsonValue() const
    37. {
    38. return QJsonValue::fromVariant(QVariant(implementation->value));
    39. }
    40. void IntDecorator::update(const QJsonObject& jsonObject)
    41. {
    42. if (jsonObject.contains(key())) {
    43. auto l_value = jsonObject.value(key()).toInt();
    44. setValue(l_value);
    45. } else {
    46. setValue(0);
    47. }
    48. }

    3.对枚举类型进行封装

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

    1. //enumerator-decorator.h
    2. #ifndef ENUMERATORDECORATOR_H
    3. #define ENUMERATORDECORATOR_H
    4. #include <map>
    5. #include <QJsonObject>
    6. #include <QJsonValue>
    7. #include <QObject>
    8. #include <QScopedPointer>
    9. #include <data/data-decorator.h>
    10. class EnumeratorDecorator : public DataDecorator
    11. {
    12. Q_OBJECT
    13. //枚举属性值
    14. Q_PROPERTY( int ui_value READ value WRITE setValue NOTIFY valueChanged )
    15. //枚举属性对应的字符串描述
    16. Q_PROPERTY( QString ui_valueDescription READ valueDescription NOTIFY valueChanged )
    17. public:
    18. EnumeratorDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", int value = 0, const std::map<int, QString>& descriptionMapper = std::map<int, QString>());
    19. ~EnumeratorDecorator();
    20. //获取属性对应的值和描述
    21. EnumeratorDecorator& setValue(int value);
    22. int value() const;
    23. QString valueDescription() const;
    24. QJsonValue jsonValue() const override;
    25. void update(const QJsonObject& jsonObject) override;
    26. signals:
    27. void valueChanged();
    28. private:
    29. class Implementation;
    30. QScopedPointer<Implementation> implementation;
    31. };
    32. #endif

    1. //enumerator-decorator.cpp
    2. #include "enumerator-decorator.h"
    3. #include <QVariant>
    4. class EnumeratorDecorator::Implementation
    5. {
    6. public:
    7. Implementation(EnumeratorDecorator* enumeratorDecorator, int value, const std::map<int, QString>& descriptionMapper)
    8. : enumeratorDecorator(enumeratorDecorator)
    9. , value(value)
    10. , descriptionMapper(descriptionMapper)
    11. {
    12. }
    13. EnumeratorDecorator* enumeratorDecorator{nullptr};
    14. int value;
    15. std::map<int, QString> descriptionMapper;
    16. };
    17. EnumeratorDecorator::EnumeratorDecorator(Entity* parentEntity, const QString& key, const QString& label, int value, const std::map<int, QString>& descriptionMapper)
    18. : DataDecorator(parentEntity, key, label)
    19. {
    20. implementation.reset(new Implementation(this, value, descriptionMapper));
    21. }
    22. EnumeratorDecorator::~EnumeratorDecorator()
    23. {
    24. }
    25. int EnumeratorDecorator::value() const
    26. {
    27. return implementation->value;
    28. }
    29. QString EnumeratorDecorator::valueDescription() const
    30. {
    31. if (implementation->descriptionMapper.find(implementation->value) != implementation->descriptionMapper.end()) {
    32. return implementation->descriptionMapper.at(implementation->value);
    33. } else {
    34. return {};
    35. }
    36. }
    37. EnumeratorDecorator& EnumeratorDecorator::setValue(int value)
    38. {
    39. if (value != implementation->value) {
    40. // ...Validation here if required...
    41. implementation->value = value;
    42. emit valueChanged();
    43. }
    44. return *this;
    45. }
    46. QJsonValue EnumeratorDecorator::jsonValue() const
    47. {
    48. return QJsonValue::fromVariant(QVariant(implementation->value));
    49. }
    50. void EnumeratorDecorator::update(const QJsonObject& jsonObject)
    51. {
    52. if (jsonObject.contains(key())) {
    53. auto valueFromJson = jsonObject.value(key()).toInt();
    54. setValue(valueFromJson);
    55. } else {
    56. setValue(0);
    57. }
    58. }

    3.对日期类型进行封装

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

    1. //datetime-decorator.h
    2. #ifndef DATETIMEDECORATOR_H
    3. #define DATETIMEDECORATOR_H
    4. #include <QDateTime>
    5. #include <QJsonObject>
    6. #include <QJsonValue>
    7. #include <QObject>
    8. #include <QScopedPointer>
    9. #include <data/data-decorator.h>
    10. class DateTimeDecorator : public DataDecorator
    11. {
    12. Q_OBJECT
    13. //QML中访问各种日期的格式
    14. Q_PROPERTY( QString ui_iso8601String READ toIso8601String NOTIFY valueChanged )
    15. Q_PROPERTY( QString ui_prettyDateString READ toPrettyDateString NOTIFY valueChanged )
    16. Q_PROPERTY( QString ui_prettyTimeString READ toPrettyTimeString NOTIFY valueChanged )
    17. Q_PROPERTY( QString ui_prettyString READ toPrettyString NOTIFY valueChanged )
    18. Q_PROPERTY( QDateTime ui_value READ value WRITE setValue NOTIFY valueChanged )
    19. public:
    20. DateTimeDecorator(Entity* parentEntity = nullptr, const QString& key = "SomeItemKey", const QString& label = "", const QDateTime& value = QDateTime());
    21. ~DateTimeDecorator();
    22. const QDateTime& value() const;
    23. DateTimeDecorator& setValue(const QDateTime& value);
    24. //获取各种显示格式
    25. QString toIso8601String() const;
    26. QString toPrettyDateString() const;
    27. QString toPrettyTimeString() const;
    28. QString toPrettyString() const;
    29. QJsonValue jsonValue() const override;
    30. void update(const QJsonObject& jsonObject) override;
    31. signals:
    32. void valueChanged();
    33. private:
    34. class Implementation;
    35. QScopedPointer<Implementation> implementation;
    36. };
    37. #endif

    1. //datetime-decorator.cpp
    2. #include "datetime-decorator.h"
    3. #include <QVariant>
    4. class DateTimeDecorator::Implementation
    5. {
    6. public:
    7. Implementation(DateTimeDecorator* dateTimeDecorator, const QDateTime& value)
    8. : dateTimeDecorator(dateTimeDecorator)
    9. , value(value)
    10. {
    11. }
    12. DateTimeDecorator* dateTimeDecorator{nullptr};
    13. QDateTime value;
    14. };
    15. DateTimeDecorator::DateTimeDecorator(Entity* parentEntity, const QString& key, const QString& label, const QDateTime& value)
    16. : DataDecorator(parentEntity, key, label)
    17. {
    18. implementation.reset(new Implementation(this, value));
    19. }
    20. DateTimeDecorator::~DateTimeDecorator()
    21. {
    22. }
    23. const QDateTime& DateTimeDecorator::value() const
    24. {
    25. return implementation->value;
    26. }
    27. DateTimeDecorator& DateTimeDecorator::setValue(const QDateTime& value)
    28. {
    29. if(value != implementation->value) {
    30. // ...Validation here if required...
    31. implementation->value = value;
    32. emit valueChanged();
    33. }
    34. return *this;
    35. }
    36. QString DateTimeDecorator::toIso8601String() const
    37. {
    38. if (implementation->value.isNull()) {
    39. return "";
    40. } else {
    41. return implementation->value.toString(Qt::ISODate);
    42. }
    43. }
    44. QString DateTimeDecorator::toPrettyString() const
    45. {
    46. if (implementation->value.isNull()) {
    47. return "Not set";
    48. } else {
    49. return implementation->value.toString( "ddd d MMM yyyy @ HH:mm:ss" );
    50. }
    51. }
    52. QString DateTimeDecorator::toPrettyDateString() const
    53. {
    54. if (implementation->value.isNull()) {
    55. return "Not set";
    56. } else {
    57. return implementation->value.toString( "d MMM yyyy" );
    58. }
    59. }
    60. QString DateTimeDecorator::toPrettyTimeString() const
    61. {
    62. if (implementation->value.isNull()) {
    63. return "Not set";
    64. } else {
    65. return implementation->value.toString( "hh:mm ap" );
    66. }
    67. }
    68. QJsonValue DateTimeDecorator::jsonValue() const
    69. {
    70. return QJsonValue::fromVariant(QVariant(implementation->value.toString(Qt::ISODate)));
    71. }
    72. void DateTimeDecorator::update(const QJsonObject& jsonObject)
    73. {
    74. if (jsonObject.contains(key())) {
    75. auto valueAsString = jsonObject.value(key()).toString();
    76. auto valueAsDate = QDateTime::fromString(valueAsString, Qt::ISODate); // yyyy-MM-ddTHH:mm:ss
    77. setValue(valueAsDate);
    78. } else {
    79. setValue(QDateTime());
    80. }
    81. }

    数据信息类封装

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

    数据实体的基类Entity封装实体需要基本属性和方法,一个数据实体包含多个基本类型的属性。同时一个数据实体可能包含多个其它的数据实体,比如一个用户可以拥有多量车多个账户等等。

    1.数据信息体封装

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

    1. //entity.h
    2. #ifndef ENTITY_H
    3. #define ENTITY_H
    4. #include <map>
    5. #include <QObject>
    6. #include <QScopedPointer>
    7. #include <data/data-decorator.h>
    8. #include <data/entity-collection.h>
    9. class Entity : public QObject
    10. {
    11. Q_OBJECT
    12. public:
    13. Entity(QObject* parent = nullptr, const QString& key = "SomeEntityKey");
    14. Entity(QObject* parent, const QString& key, const QJsonObject& jsonObject);
    15. virtual ~Entity();
    16. public:
    17. //数据信息体对应的key值
    18. const QString& key() const;
    19. //数据信息类和Json结构之间的相互转换
    20. void update(const QJsonObject& jsonObject);
    21. QJsonObject toJson() const;
    22. signals:
    23. //信息体集合发生变化
    24. void childCollectionsChanged(const QString& collectionKey);
    25. //包含的信息体发生变化
    26. void childEntitiesChanged();
    27. //包含的属性发生变化
    28. void dataDecoratorsChanged();
    29. protected:
    30. //添加包含的信信息体
    31. Entity* addChild(Entity* entity, const QString& key);
    32. //添加包含的信息实体列表
    33. EntityCollectionBase* addChildCollection(EntityCollectionBase* entityCollection);
    34. //添加子属性
    35. DataDecorator* addDataItem(DataDecorator* dataDecorator);
    36. protected:
    37. class Implementation;
    38. QScopedPointer<Implementation> implementation;
    39. };
    40. #endif

    1. //entity.cpp
    2. #include "entity.h"
    3. #include <QJsonArray>
    4. class Entity::Implementation
    5. {
    6. public:
    7. Implementation(Entity* _entity, const QString& _key)
    8. : entity(_entity)
    9. , key(_key)
    10. {
    11. }
    12. Entity* entity{nullptr};
    13. QString key;
    14. std::map<QString, EntityCollectionBase*> childCollections;
    15. std::map<QString, Entity*> childEntities;
    16. std::map<QString, DataDecorator*> dataDecorators;
    17. };
    18. Entity::Entity(QObject* parent, const QString& key)
    19. : QObject(parent)
    20. {
    21. implementation.reset(new Implementation(this, key));
    22. }
    23. Entity::Entity(QObject* parent, const QString& key, const QJsonObject& jsonObject)
    24. : Entity(parent, key)
    25. {
    26. update(jsonObject);
    27. }
    28. Entity::~Entity()
    29. {
    30. }
    31. const QString& Entity::key() const
    32. {
    33. return implementation->key;
    34. }
    35. Entity* Entity::addChild(Entity* entity, const QString& key)
    36. {
    37. if(implementation->childEntities.find(key) == std::end(implementation->childEntities)) {
    38. implementation->childEntities[key] = entity;
    39. emit childEntitiesChanged();
    40. }
    41. return entity;
    42. }
    43. EntityCollectionBase* Entity::addChildCollection(EntityCollectionBase* entityCollection)
    44. {
    45. if(implementation->childCollections.find(entityCollection->getKey()) == std::end(implementation->childCollections)) {
    46. implementation->childCollections[entityCollection->getKey()] = entityCollection;
    47. emit childCollectionsChanged(entityCollection->getKey());
    48. }
    49. return entityCollection;
    50. }
    51. DataDecorator* Entity::addDataItem(DataDecorator* dataDecorator)
    52. {
    53. if(implementation->dataDecorators.find(dataDecorator->key()) == std::end(implementation->dataDecorators)) {
    54. implementation->dataDecorators[dataDecorator->key()] = dataDecorator;
    55. emit dataDecoratorsChanged();
    56. }
    57. return dataDecorator;
    58. }
    59. void Entity::update(const QJsonObject& jsonObject)
    60. {
    61. // Update data decorators
    62. for (std::pair<QString, DataDecorator*> dataDecoratorPair : implementation->dataDecorators) {
    63. dataDecoratorPair.second->update(jsonObject);
    64. }
    65. // Update child entities
    66. for (std::pair<QString, Entity*> childEntityPair : implementation->childEntities) {
    67. childEntityPair.second->update(jsonObject.value(childEntityPair.first).toObject());
    68. }
    69. // Update child collections
    70. for (std::pair<QString, EntityCollectionBase*> childCollectionPair : implementation->childCollections) {
    71. childCollectionPair.second->update(jsonObject.value(childCollectionPair.first).toArray());
    72. }
    73. }
    74. QJsonObject Entity::toJson() const
    75. {
    76. QJsonObject returnValue;
    77. // Add data decorators
    78. for (std::pair<QString, DataDecorator*> dataDecoratorPair : implementation->dataDecorators) {
    79. returnValue.insert( dataDecoratorPair.first, dataDecoratorPair.second->jsonValue() );
    80. }
    81. // Add child entities
    82. for (std::pair<QString, Entity*> childEntityPair : implementation->childEntities) {
    83. returnValue.insert( childEntityPair.first, childEntityPair.second->toJson() );
    84. }
    85. // Add child collections
    86. for (std::pair<QString, EntityCollectionBase*> childCollectionPair : implementation->childCollections) {
    87. QJsonArray entityArray;
    88. for (Entity* entity : childCollectionPair.second->baseEntities()) {
    89. entityArray.append( entity->toJson() );
    90. }
    91. returnValue.insert( childCollectionPair.first, entityArray );
    92. }
    93. return returnValue;
    94. }

    2.数据信息集合封装

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

    1. #ifndef ENTITYCOLLECTION_H
    2. #define ENTITYCOLLECTION_H
    3. #include <QJsonArray>
    4. #include <QJsonValue>
    5. #include <QObject>
    6. class Entity;
    7. //基类声明集合变化的信号
    8. class EntityCollectionObject : public QObject
    9. {
    10. Q_OBJECT
    11. public:
    12. EntityCollectionObject(QObject* _parent = nullptr) : QObject(_parent) {}
    13. virtual ~EntityCollectionObject() {}
    14. signals:
    15. void collectionChanged();
    16. };
    17. //数据信息集合的基类
    18. class EntityCollectionBase : public EntityCollectionObject
    19. {
    20. public:
    21. EntityCollectionBase(QObject* parent = nullptr, const QString& key = "SomeCollectionKey")
    22. : EntityCollectionObject(parent)
    23. , key(key)
    24. {}
    25. virtual ~EntityCollectionBase()
    26. {}
    27. QString getKey() const
    28. {
    29. return key;
    30. }
    31. virtual void clear() = 0;
    32. //json数组转成数据实体
    33. virtual void update(const QJsonArray& json) = 0;
    34. virtual std::vector<Entity*> baseEntities() = 0;
    35. template <class T>
    36. QList<T*>& derivedEntities();
    37. template <class T>
    38. T* addEntity(T* entity);
    39. private:
    40. QString key;
    41. };
    42. //数据信息基类
    43. template <typename T>
    44. class EntityCollection : public EntityCollectionBase
    45. {
    46. public:
    47. EntityCollection(QObject* parent = nullptr, const QString& key = "SomeCollectionKey")
    48. : EntityCollectionBase(parent, key)
    49. {}
    50. ~EntityCollection()
    51. {}
    52. //清空列表
    53. void clear() override
    54. {
    55. for(auto entity : collection) {
    56. entity->deleteLater();
    57. }
    58. collection.clear();
    59. }
    60. //更新列表
    61. void update(const QJsonArray& jsonArray) override
    62. {
    63. clear();
    64. for(const QJsonValue& jsonValue : jsonArray) {
    65. addEntity(new T(this, jsonValue.toObject()));
    66. }
    67. }
    68. //获取列表
    69. std::vector<Entity*> baseEntities() override
    70. {
    71. std::vector<Entity*> returnValue;
    72. for(T* entity : collection) {
    73. returnValue.push_back(entity);
    74. }
    75. return returnValue;
    76. }
    77. //获取列表的引用
    78. QList<T*>& derivedEntities()
    79. {
    80. return collection;
    81. }
    82. //添加新的信息实体
    83. T* addEntity(T* entity)
    84. {
    85. if(!collection.contains(entity)) {
    86. collection.append(entity);
    87. EntityCollectionObject::collectionChanged();
    88. }
    89. return entity;
    90. }
    91. private:
    92. QList<T*> collection;
    93. };
    94. template <class T>
    95. QList<T*>& EntityCollectionBase::derivedEntities()
    96. {
    97. return dynamic_cast<const EntityCollection<T>&>(*this).derivedEntities();
    98. }
    99. template <class T>
    100. T* EntityCollectionBase::addEntity(T* entity)
    101. {
    102. return dynamic_cast<const EntityCollection<T>&>(*this).addEntity(entity);
    103. }
    104. #endif

    使用封装的数据结构

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

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

    1. //address.h
    2. #ifndef ADDRESS_H
    3. #define ADDRESS_H
    4. #include <QObject>
    5. #include <data/string-decorator.h>
    6. #include <data/entity.h>
    7. class Address : public Entity
    8. {
    9. Q_OBJECT
    10. Q_PROPERTY(StringDecorator* ui_building MEMBER building CONSTANT)
    11. Q_PROPERTY(StringDecorator* ui_street MEMBER street CONSTANT)
    12. Q_PROPERTY(StringDecorator* ui_city MEMBER city CONSTANT)
    13. Q_PROPERTY(StringDecorator* ui_postcode MEMBER postcode CONSTANT)
    14. Q_PROPERTY(QString ui_fullAddress READ fullAddress CONSTANT)
    15. public:
    16. explicit Address(QObject* parent = nullptr);
    17. Address(QObject* parent, const QJsonObject& json);
    18. StringDecorator* building{nullptr}; //建筑
    19. StringDecorator* street{nullptr}; //街道
    20. StringDecorator* city{nullptr}; //城市
    21. StringDecorator* postcode{nullptr}; //邮政编码
    22. QString fullAddress() const;
    23. };
    24. #endif
    1. //address.cpp
    2. #include "address.h"
    3. Address::Address(QObject* parent)
    4. : Entity(parent, "address")
    5. {
    6. building = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "building", "Building")));
    7. street = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "street", "Street")));
    8. city = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "city", "City")));
    9. postcode = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "postcode", "Post Code")));
    10. }
    11. Address::Address(QObject* parent, const QJsonObject& json)
    12. : Address(parent)
    13. {
    14. update(json);
    15. }
    16. QString Address::fullAddress() const
    17. {
    18. return building->value() + " " + street->value() + "\n" + city->value() + "\n" + postcode->value();
    19. }

    消费者信息类中除了包含基本属性之外,还包含一个地址信息集合,对应的实现如下:

    1. //customer.h
    2. #ifndef Customer_H
    3. #define Customer_H
    4. #include <QObject>
    5. #include <QtQml/QQmlListProperty>
    6. #include <data/string-decorator.h>
    7. #include <data/int-decorator.h>
    8. #include <data/entity.h>
    9. #include <data/entity-collection.h>
    10. #include <data/address.h>
    11. class Customer : public Entity
    12. {
    13. Q_OBJECT
    14. //QML访问的信息接口
    15. //年龄信息
    16. Q_PROPERTY( IntDecorator* ui_age MEMBER age CONSTANT )
    17. //姓名信息
    18. Q_PROPERTY( StringDecorator* ui_name MEMBER name CONSTANT )
    19. Q_PROPERTY( Address* ui_mainAddress MEMBER defaultAddr CONSTANT ) //默认地址
    20. //地址列表
    21. Q_PROPERTY( QQmlListProperty<Address> ui_address READ ui_address NOTIFY addresssListChanged)
    22. public:
    23. explicit Customer(QObject* parent = nullptr);
    24. Customer(QObject* parent, const QJsonObject& json);
    25. IntDecorator* age{nullptr}; //年龄
    26. StringDecorator* name{nullptr}; //姓名
    27. Address* defaultAddr{nullptr}; //默认地址
    28. //地址列表
    29. EntityCollection<Address>* addresses{nullptr};
    30. //qml访问的地址列表
    31. QQmlListProperty<Address> ui_address();
    32. signals:
    33. void addresssListChanged();
    34. };
    35. #endif
    1. //customer.cpp
    2. #include "customer.h"
    3. Customer::Customer(QObject* parent)
    4. : Entity(parent, "Customer")
    5. {
    6. age = static_cast<IntDecorator*>(addDataItem(new IntDecorator(this, "age", "年龄")));
    7. name = static_cast<StringDecorator*>(addDataItem(new StringDecorator(this, "name", "姓名")));
    8. defaultAddr = static_cast<Address*>(addChild(new Address(this), "defaultAddress"));
    9. addresses = static_cast<EntityCollection<Address>*>(addChildCollection(new EntityCollection<Address>(this, "address")));
    10. }
    11. Customer::Customer(QObject* parent, const QJsonObject& json)
    12. : Customer(parent)
    13. {
    14. update(json);
    15. }
    16. QQmlListProperty<Address> Customer::ui_address()
    17. {
    18. return QQmlListProperty<Address>(this, addresses->derivedEntities());
    19. }

    2.使用新的数据类型

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

    1. #include "widget.h"
    2. #include <QApplication>
    3. #include <data/customer.h>
    4. #include <data/address.h>
    5. int main(int argc, char *argv[])
    6. {
    7. QApplication a(argc, argv);
    8. //将json结构转换成一个数据类
    9. QJsonObject customer_json;
    10. Customer* customer = new Customer(NULL,customer_json);
    11. //名字变化处理
    12. QObject::connect(customer->name,&StringDecorator::valueChanged,[&](){});
    13. //年龄变化的处理
    14. QObject::connect(customer->age,&IntDecorator::valueChanged,[&](){});
    15. //默认地址变化的处理
    16. QObject::connect(customer->defaultAddr,&Address::dataDecoratorsChanged,[&](){});
    17. //修改数据
    18. customer->name->setValue("小明");
    19. customer->age->setValue(23);
    20. customer->defaultAddr->city->setValue("北京市");
    21. customer->defaultAddr->street->setValue("光明街道");
    22. customer->defaultAddr->building->setValue("6号楼");
    23. customer->defaultAddr->postcode->setValue("56788");
    24. //添加新地址
    25. Address* new_addr = new Address();
    26. new_addr->city->setValue("西河市");
    27. new_addr->street->setValue("细节街道");
    28. new_addr->building->setValue("6号楼");
    29. new_addr->postcode->setValue("56789");
    30. customer->addresses->addEntity(new_addr);
    31. //将数据类型转换成json数据结构
    32. QJsonObject json_object = customer->toJson();
    33. return a.exec();
    34. }

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

  • 相关阅读:
    pandas是什么以及pandas的三种数据结构Series、DataFrame、MultiIndex的创建方式函数代码
    全职RISC-V芯片D1开发板使用adb串口COM连接设备和文件上传下载
    深度神经网络预测模型,人工神经网络回归分析
    HCIP学习--扩展知识点
    艾美捷测序级 II,纯化胰蛋白酶化验程序&文献参考
    UG\NX二次开发 实时查看 NX 日志文件
    理解MTU VLAN与端口VLAN两个概念
    远程运维如何更高效的远程管理?向日葵的这几项功能会帮到你
    【附源码】Python计算机毕业设计网上购物平台
    Nested loop(PostgreSQL 14 Internals翻译版)
  • 原文地址:https://blog.csdn.net/yang1fei2/article/details/125032738