Qt QJsonDocument 的使用小结
作者:华丽的周遭
一、QJsonDocument 概述
QJsonDocument是 Qt 中处理 JSON 数据的核心容器类,属于 QtCore模块(需包含头文件 <QJsonDocument>,并在 .pro中添加 QT += core)。它的核心作用是:
- 解析 JSON 字符串/字节流为结构化的 Qt 对象(
QJsonObject/QJsonArray); - 生成 JSON 字符串/字节流(从
QJsonObject/QJsonArray转换); - 封装 JSON 文档的根元素(JSON 根必须是对象或数组,不能是单个值)。
Qt 的 JSON 模块是轻量级、隐式共享(Implicitly Shared)的,适合嵌入式场景,资源占用低且性能足够。
二、核心功能与用法
1. 解析 JSON(从字符串/字节流到 Qt 对象)
使用静态方法 QJsonDocument::fromJson()解析 JSON 数据,需传入UTF-8 编码的 QByteArray(若源是 QString,需用 toUtf8()转换)。
关键细节:
- 错误处理:通过
QJsonParseError结构体获取解析错误(如语法错误、非法字符); - 根元素判断:解析后需用
isObject()/isArray()判断根类型是对象还是数组。
示例:解析 JSON 字符串
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void parseJsonExample() {
// 1. 待解析的 JSON 字符串(UTF-8)
QString jsonStr = R"({
"device": "Portable Monitor",
"model": "PM-2024",
"stream": {
"url": "rtsp://192.168.1.100/live",
"codec": "H265",
"resolution": "1920x1080",
"fps": 30
},
"status": ["online", "recording"]
})";
// 2. 转换为 UTF-8 字节流
QByteArray jsonData = jsonStr.toUtf8();
// 3. 解析并捕获错误
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qDebug() << "JSON 解析失败:" << parseError.errorString()
<< "(位置:" << parseError.offset << ")";
return;
}
// 4. 访问根元素(此处是对象)
if (doc.isObject()) {
QJsonObject rootObj = doc.object();
// 读取简单键值
QString device = rootObj["device"].toString(); // "Portable Monitor"
QString model = rootObj["model"].toString(); // "PM-2024"
// 读取嵌套对象(stream)
QJsonObject streamObj = rootObj["stream"].toObject();
QString rtspUrl = streamObj["url"].toString(); // "rtsp://..."
QString codec = streamObj["codec"].toString(); // "H265"
int fps = streamObj["fps"].toInt(); // 30
// 读取数组(status)
QJsonArray statusArr = rootObj["status"].toArray();
for (const QJsonValue &val : statusArr) {
qDebug() << "状态:" << val.toString(); // "online", "recording"
}
}
}2. 生成 JSON(从 Qt 对象到字符串/字节流)
使用 QJsonDocument::toJson()将 QJsonObject/QJsonArray转换为 JSON 字符串,支持两种格式:
QJsonDocument::Compact:紧凑模式(无缩进,适合网络传输);QJsonDocument::Indented:缩进模式(带换行和空格,适合日志/调试)。
示例:生成 JSON 配置
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void generateJsonExample() {
// 1. 构建嵌套的 JSON 对象(模拟流媒体配置)
QJsonObject streamObj;
streamObj["url"] = "rtsp://192.168.1.101/preview";
streamObj["codec"] = "H264";
streamObj["resolution"] = "1280x720";
streamObj["fps"] = 25;
streamObj["protocol"] = "TCP"; // 流媒体常用 TCP/UDP
// 2. 构建根对象
QJsonObject rootObj;
rootObj["device"] = "Portable Monitor";
rootObj["model"] = "PM-2024";
rootObj["stream"] = streamObj; // 嵌套对象
rootObj["features"] = QJsonArray::fromStringList({"HDMI", "USB-C", "WiFi"}); // 数组
// 3. 封装为 QJsonDocument(根元素是对象)
QJsonDocument doc(rootObj);
// 4. 转换为 JSON 字符串(缩进模式,方便阅读)
QByteArray jsonData = doc.toJson(QJsonDocument::Indented);
QString jsonStr = QString::fromUtf8(jsonData);
qDebug() << "生成的 JSON:\n" << jsonStr;
/* 输出:
{
"device": "Portable Monitor",
"features": ["HDMI", "USB-C", "WiFi"],
"model": "PM-2024",
"stream": {
"codec": "H264",
"fps": 25,
"protocol": "TCP",
"resolution": "1280x720",
"url": "rtsp://192.168.1.101/preview"
}
}
*/
}3. 核心方法与属性
方法/属性 | 说明 |
|---|---|
QJsonDocument() | 默认构造(空文档,isNull()/isEmpty()均为 true) |
QJsonDocument(const QJsonObject&) | 用 JSON 对象初始化(根为对象) |
QJsonDocument(const QJsonArray&) | 用 JSON 数组初始化(根为数组) |
static QJsonDocument fromJson(const QByteArray&, QJsonParseError*) | 解析 JSON 字节流,返回文档+错误信息 |
QByteArray toJson(Format format = Compact) | 转换为 JSON 字节流(Compact/Indented) |
bool isObject() const | 根元素是否为 JSON 对象 |
bool isArray() const | 根元素是否为 JSON 数组 |
QJsonObject object() const | 获取根对象(若根是数组,返回空对象) |
QJsonArray array() const | 获取根数组(若根是对象,返回空数组) |
bool isEmpty() const | 文档是否为空(默认构造或未初始化) |
bool isNull() const | 文档是否无效(同 isEmpty(),部分版本差异可忽略) |
void swap(QJsonDocument&) | 交换两个文档的内容(高效) |
三、与其他 QJson 类的协作
QJsonDocument是容器,需配合以下类完成完整的 JSON 处理:
类名 | 作用 |
|---|---|
QJsonValue | JSON 基本值的封装(null/bool/int/double/string/object/array) |
QJsonObject | JSON 对象(键值对集合,类似 std::map<QString, QJsonValue>) |
QJsonArray | JSON 数组(有序值集合,类似 QList<QJsonValue>) |
QJsonParseError | 解析错误的详细信息(error枚举+offset错误位置) |
关系链:
QJsonDocument→ 包含 QJsonObject/QJsonArray→ 包含 QJsonValue→ 对应 JSON 基本类型。
四、实际场景应用
用 ZynqMP + Qt 开发,流媒体是核心方向。QJsonDocument可用于以下场景:
1. 流媒体配置管理
用 JSON 存储设备的流媒体参数(如 RTSP 地址、编码格式、分辨率),通过 QJsonDocument解析后配置播放器。
示例配置 JSON:
{
"stream": {
"input": "rtsp://admin:123@192.168.1.100/stream1",
"decoder": "H265",
"resolution": "1920x1080",
"fps": 30,
"buffer_size": 1024
},
"display": {
"brightness": 70,
"contrast": 50,
"fullscreen": false
}
}解析后:提取 stream.input给 GStreamer/FFmpeg 播放器,display.brightness调整屏幕亮度。
2. 设备状态上报
将监视器的实时状态(如播放状态、码率、温度、剩余电量)封装为 JSON,通过 HTTP/MQTT 上报到服务器。
示例状态 JSON:
{
"device_id": "PM-2024-001",
"timestamp": 1718236800,
"status": {
"play_state": "playing",
"bitrate": 2048,
"fps": 29.97,
"temperature": 45,
"battery": 80
}
}生成后:用 QNetworkAccessManager发送 POST 请求。
3. 固件/配置更新
通过 JSON 描述更新包的信息(版本号、下载地址、校验和),解析后触发 OTA 升级。
五、注意事项与常见问题
1. 编码问题
JSON 标准要求UTF-8 编码,QJsonDocument仅支持 UTF-8。若源数据是 GBK 等其他编码,需先转换为 UTF-8(用 QString::fromLocal8Bit()或 QTextCodec)。
2. 根元素限制
JSON 根必须是对象或数组,不能直接是字符串/数字。若要存储单个值,需用对象包装:
// 错误:根是字符串
// QJsonDocument doc("hello");
// 正确:用对象包装
QJsonObject obj;
obj["message"] = "hello";
QJsonDocument doc(obj);3. 错误处理
解析前务必检查 QJsonParseError:
常见错误:QJsonParseError::IllegalValue(非法值)、QJsonParseError::MissingObject(缺少对象)、QJsonParseError::SyntaxError(语法错误)。
4. 性能优化
- 隐式共享:
QJsonDocument拷贝时是浅拷贝,修改时才深拷贝,避免不必要的内存开销; - 大文档处理:若 JSON 文档过大(如超过 10MB),建议用流式解析(Qt 未提供原生流式 API,可考虑第三方库如
simdjson),但嵌入式场景下很少遇到。
5. 键不存在的处理
访问 QJsonObject的不存在的键时,返回无效的 QJsonValue(isUndefined()为 true)。需用以下方式安全取值:
QJsonObject obj = ...;
// 方法1:先判断键存在
if (obj.contains("stream_url")) {
QString url = obj["stream_url"].toString();
}
// 方法2:用 value() 取默认值
QString url = obj.value("stream_url").toString("rtsp://default.url");六、扩展:QVariant 与 JSON 的转换
QJsonDocument提供 fromVariant()/toVariant()方法,可将 QVariantMap(对应 JSON 对象)、QVariantList(对应 JSON 数组)与 JSON 互转,简化 Qt 数据结构与 JSON 的交互:
// QVariantMap → JSON QVariantMap config; config["device"] = "PM-2024"; config["stream_url"] = "rtsp://..."; QJsonDocument doc = QJsonDocument::fromVariant(config); // JSON → QVariantMap QVariantMap config2 = doc.toVariant().toMap();
总结
QJsonDocument是 Qt 处理 JSON 的核心入口,结合 QJsonObject/QJsonArray可轻松实现 JSON 的解析与生成。
到此这篇关于Qt QJsonDocument 的使用小结的文章就介绍到这了,更多相关Qt QJsonDocument 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
