QJson

  1. `QJsonValue`

• 是什么:JSON 值的基础单元。一个 `QJsonValue` 对象可以封装 JSON 支持的任何一种数据类型:`null`, `bool`, `double`, `string`, `array`, `object`。

• 常用函数:

• 构造函数:`QJsonValue(bool b)`, `QJsonValue(double n)`, `QJsonValue(const QString &s)`, `QJsonValue(const QJsonArray &a)`, `QJsonValue(const QJsonObject &o)`。

• 类型判断:`isBool()`, `isDouble()`, `isString()`, `isArray()`, `isObject()`, `isNull()`, `isUndefined()`。

• 类型转换/获取值:`toBool()`, `toDouble()`, `toString()`, `toArray()`, `toObject()`。

• 注意:在转换前最好先用 `is...()` 函数判断类型,否则可能得到默认值(如 `false`, `0`, 空字符串等)。   

  1. `QJsonObject`

• 是什么:表示一个 JSON 对象(`{ "key": value, ... }`)。它是一个键值对的集合,其中键(key)是 `QString`,值(value)是 `QJsonValue`。本质上非常像一个 `QMap<QString, QJsonValue>`。

• 常用函数:

• 插入/修改:`insert(const QString &key, const QJsonValue &value)` 或使用 `operator[]`,例如 `jsonObject["name"] = "Alice";`。

• 获取值:`value(const QString &key)` 或 `operator[]`。`value()` 函数更安全,如果键不存在,会返回一个 `Undefined` 类型的 `QJsonValue`。

• 检查键是否存在:`contains(const QString &key)`。 • 获取所有键:`keys()`,返回一个 `QStringList`。

• 获取大小:`size()` 或 `count()`。

• 移除键值对:`remove(const QString &key)`。   

  1. `QJsonArray`

• 是什么:表示一个 JSON 数组(`[ value1, value2, ... ]`)。它是一个 `QJsonValue` 的有序列表,非常像 `QList<QJsonValue>`。

• 常用函数:

• 添加元素:`append(const QJsonValue &value)` 或 `push_back()`。 • 插入元素:`insert(int i, const QJsonValue &value)`。

• 获取元素:`at(int i)` 或 `operator[]`。

• 获取大小:`size()` 或 `count()`。

• 移除元素:`removeAt(int i)`。

• 遍历:可以使用 C++11 的 range-based for循环 (`for (const QJsonValue &val : jsonArray)`)或传统的索引循环。   

  1. `QJsonDocument`

• 是什么:JSON 文档的容器。一个完整的、有效的JSON文本要么是一个对象,要么是一个数组。`QJsonDocument` 就是用来包装这个顶层对象或数组,并负责与外部世界(如 `QString` 或 `QByteArray`)进行转换。

• 常用函数:

• 从JSON文本创建 (解析): • `static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = nullptr)`。这是最常用的解析函数。传入包含JSON文本的字节数组,如果解析出错,错误信息会存入 `error` 对象。

• `static QJsonDocument fromVariant(const QVariant &variant)`:从 `QVariantMap` 或 `QVariantList` 创建。  

• 生成JSON文本:

• `QByteArray toJson(JsonFormat format = Indented) const`。将文档转换为字节数组。`format` 可以是 `Indented` (带缩进,易读) 或 `Compact` (无空格,节省空间)。  

• 获取顶层元素:

• `isObject()` / `isArray()`:判断顶层元素是对象还是数组。

• `object()`:如果顶层是对象,返回 `QJsonObject`。

• `array()`:如果顶层是数组,返回 `QJsonArray`。  

• 设置顶层元素:

• `setObject(const QJsonObject &object)`。

• `setArray(const QJsonArray &array)`。

QVariantMap` 是什么:

`QVariantMap` 是 `QMap<QString, QVariant>` 的一个 `typedef`(类型别名)。它是一个键为 `QString`、值为 `QVariant` 的映射。

`QVariant` 是一个可以存储多种 Qt 数据类型的联合体类(如 `int`, `QString`, `QColor`, `QList` 等)。

• 与 `QJsonObject` 的区别与联系:

• `QJsonObject` 的值必须是 `QJsonValue`,其类型范围严格受限于 JSON 标准。

• `QVariantMap` 的值是 `QVariant`,可以存储任何 Qt 已知的数据类型,范围远大于 JSON。  

• 转换:由于结构上的相似性,Qt 提供了非常方便的转换方法。

• `QVariantMap` -> `QJsonObject`:
 

QVariantMap map;
map["name"] = "Bob";
map["age"] = 30;

QJsonObject jsonObj = QJsonObject::fromVariantMap(map);    

• `QJsonObject` -> `QVariantMap`:

QJsonObject jsonObj; // 假设已有数据
QVariantMap map = jsonObj.toVariantMap();    

• `QVariantList` -> `QJsonArray`:

`QVariantList` (`QList<QVariant>`) 也可以轻松转换为 `QJsonArray`。

QVariantList list;
list.append(1);
list.append("apple");
QJsonArray jsonArr = QJsonArray::fromVariantList(list);

QVariantList newList = jsonArr.toVariantList();       

为什么需要这种转换? 在很多 Qt 应用中,数据模型可能使用 `QVariantMap` 和 `QVariantList` 来存储,因为它们更通用。当需要将这些数据序列化为 JSON 字符串,就可以先将它们转换为 `QJsonObject` / `QJsonArray`,然后再用 `QJsonDocument` 生成字符串。反之亦然。

其他容器

QList<T>`

• 特点:

• 混合实现:内部实现是数组和链表的混合体。对于少量元素,它的行为像一个动态数组,提供快速的索引访问 (`O(1)`)。当元素数量增长超过一定阈值时,它可能会转换为类似链表的结构来优化插入和删除操作。

• 快速的头部和尾部操作:`append()` 和 `prepend()` (在头部添加) 操作通常非常快(摊销 `O(1)`)。

• 索引访问快:通过 `operator[]` 或 `at()` 进行索引访问很快(`O(1)`)。

• 中间插入/删除慢:在列表的中间插入或删除元素可能很慢(`O(n)`),因为它需要移动后续所有元素。

• 隐式共享 (Copy-on-Write):`QList` 的拷贝操作非常快,因为它只复制一个指向内部数据的指针和引用计数。只有当某个副本被修改时,才会真正复制数据。这极大地优化了函数按值传递容器的性能。

• 最常用的序列容器:在大多数情况下,如果你需要一个有序列表,`QList` 是首选。   

2. `QVector<T>`

• 特点:

• 纯数组实现:总是在内存中存储为一块连续的数组。

• 最快的索引访问:提供最快的索引访问速度(`O(1)`),比 `QList` 略快且更稳定。

• 快速的尾部操作:`append()` 操作是摊销 `O(1)` 的。

• 头部/中间插入删除非常慢:在头部或中间进行插入/删除操作非常慢(`O(n)`),因为需要移动大量元素。

• 内存连续:保证元素在内存中是连续存储的,这对于与需要指针和元素计数的 C 风格 API 交互非常有用 (`data()` 函数返回的指针可以直接用)。

• 适用场景:当你需要极快的索引访问、主要在尾部添加元素,并且需要内存连续性时,`QVector` 是最佳选择。   

3. `QMap<Key, T>`

• 特点:

• 键值对容器:存储 (Key, Value) 对。

• 按键排序:内部使用红黑树实现。元素总是按照键(Key)的升序排列。

• 查找/插入/删除速度:对数时间复杂度(`O(log n)`),因为是基于树的结构。

• 键的唯一性:一个 `QMap` 中不能有重复的键。插入一个已存在的键会覆盖旧的值。

• 隐式共享 (Copy-on-Write):同 `QList`。

• 适用场景:当你需要一个按键排序的字典,并且对查找、插入、删除性能有稳定预期(`O(log n)`)时使用。   

4. `QHash<Key, T>`

• 特点:

• 键值对容器:同 `QMap`。

• 无序:内部使用哈希表实现。元素的存储顺序是无序的,并且可能会在哈希表重建时改变。

• 查找/插入/删除速度:平均情况下非常快,为常数时间复杂度(`O(1)`)。最坏情况下(哈希冲突严重)会退化到 `O(n)`,但这种情况很少见。

• 键的要求:键类型 `Key` 必须提供一个全局的 `qHash(Key)` 函数和一个 `operator==`。Qt 为常用类型内置了 `qHash`。

• 隐式共享 (Copy-on-Write):同 `QList`。

• 适用场景:当你需要最快的查找速度,且不关心元素顺序时,`QHash` 是最佳选择。`QJsonObject` 的底层实现就类似于 `QHash`。  

5. `QSet<T>`

特点:

• 值的集合:只存储值,不存储键。

• 唯一性:集合中的每个元素都是唯一的。尝试插入一个已存在的元素不会有任何效果。 • 无序:基于 哈希表 实现,与 `QHash` 类似,元素是无序的。

• 快速查找:提供了非常快的查找操作 (`contains()`),平均时间复杂度为 `O(1)`。

• 值的要求:同 `QHash` 的键,类型 `T` 需要 `qHash()` 函数和 `operator==`。

• 集合操作:提供了丰富的集合操作,如 `unite()` (并集), `intersect()` (交集), `subtract()` (差集)。

• 适用场景:当你需要存储一组唯一的元素,并快速检查某个元素是否存在时,`QSet` 是理想选择。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐