
一、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 字符串
cpp
#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 配置
cpp
#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 的解析与生成。
