Qt QJsonDocument 的使用小結(jié)
一、QJsonDocument 概述
QJsonDocument是 Qt 中處理 JSON 數(shù)據(jù)的核心容器類,屬于 QtCore模塊(需包含頭文件 <QJsonDocument>,并在 .pro中添加 QT += core)。它的核心作用是:
- 解析? JSON 字符串/字節(jié)流為結(jié)構(gòu)化的 Qt 對(duì)象(
QJsonObject/QJsonArray); - 生成? JSON 字符串/字節(jié)流(從
QJsonObject/QJsonArray轉(zhuǎn)換); - 封裝? JSON 文檔的根元素(JSON 根必須是對(duì)象或數(shù)組,不能是單個(gè)值)。
Qt 的 JSON 模塊是輕量級(jí)、隱式共享(Implicitly Shared)的,適合嵌入式場(chǎng)景,資源占用低且性能足夠。
二、核心功能與用法
1. 解析 JSON(從字符串/字節(jié)流到 Qt 對(duì)象)
使用靜態(tài)方法 QJsonDocument::fromJson()解析 JSON 數(shù)據(jù),需傳入UTF-8 編碼的 QByteArray(若源是 QString,需用 toUtf8()轉(zhuǎn)換)。
關(guān)鍵細(xì)節(jié):
- 錯(cuò)誤處理:通過
QJsonParseError結(jié)構(gòu)體獲取解析錯(cuò)誤(如語法錯(cuò)誤、非法字符); - 根元素判斷:解析后需用
isObject()/isArray()判斷根類型是對(duì)象還是數(shù)組。
示例:解析 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. 轉(zhuǎn)換為 UTF-8 字節(jié)流
QByteArray jsonData = jsonStr.toUtf8();
// 3. 解析并捕獲錯(cuò)誤
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qDebug() << "JSON 解析失?。? << parseError.errorString()
<< "(位置:" << parseError.offset << ")";
return;
}
// 4. 訪問根元素(此處是對(duì)象)
if (doc.isObject()) {
QJsonObject rootObj = doc.object();
// 讀取簡(jiǎn)單鍵值
QString device = rootObj["device"].toString(); // "Portable Monitor"
QString model = rootObj["model"].toString(); // "PM-2024"
// 讀取嵌套對(duì)象(stream)
QJsonObject streamObj = rootObj["stream"].toObject();
QString rtspUrl = streamObj["url"].toString(); // "rtsp://..."
QString codec = streamObj["codec"].toString(); // "H265"
int fps = streamObj["fps"].toInt(); // 30
// 讀取數(shù)組(status)
QJsonArray statusArr = rootObj["status"].toArray();
for (const QJsonValue &val : statusArr) {
qDebug() << "狀態(tài):" << val.toString(); // "online", "recording"
}
}
}2. 生成 JSON(從 Qt 對(duì)象到字符串/字節(jié)流)
使用 QJsonDocument::toJson()將 QJsonObject/QJsonArray轉(zhuǎn)換為 JSON 字符串,支持兩種格式:
QJsonDocument::Compact:緊湊模式(無縮進(jìn),適合網(wǎng)絡(luò)傳輸);QJsonDocument::Indented:縮進(jìn)模式(帶換行和空格,適合日志/調(diào)試)。
示例:生成 JSON 配置?
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void generateJsonExample() {
// 1. 構(gòu)建嵌套的 JSON 對(duì)象(模擬流媒體配置)
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. 構(gòu)建根對(duì)象
QJsonObject rootObj;
rootObj["device"] = "Portable Monitor";
rootObj["model"] = "PM-2024";
rootObj["stream"] = streamObj; // 嵌套對(duì)象
rootObj["features"] = QJsonArray::fromStringList({"HDMI", "USB-C", "WiFi"}); // 數(shù)組
// 3. 封裝為 QJsonDocument(根元素是對(duì)象)
QJsonDocument doc(rootObj);
// 4. 轉(zhuǎn)換為 JSON 字符串(縮進(jìn)模式,方便閱讀)
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() | 默認(rèn)構(gòu)造(空文檔,isNull()/isEmpty()均為 true) |
QJsonDocument(const QJsonObject&) | 用 JSON 對(duì)象初始化(根為對(duì)象) |
QJsonDocument(const QJsonArray&) | 用 JSON 數(shù)組初始化(根為數(shù)組) |
static QJsonDocument fromJson(const QByteArray&, QJsonParseError*) | 解析 JSON 字節(jié)流,返回文檔+錯(cuò)誤信息 |
QByteArray toJson(Format format = Compact) | 轉(zhuǎn)換為 JSON 字節(jié)流(Compact/Indented) |
bool isObject() const | 根元素是否為 JSON 對(duì)象 |
bool isArray() const | 根元素是否為 JSON 數(shù)組 |
QJsonObject object() const | 獲取根對(duì)象(若根是數(shù)組,返回空對(duì)象) |
QJsonArray array() const | 獲取根數(shù)組(若根是對(duì)象,返回空數(shù)組) |
bool isEmpty() const | 文檔是否為空(默認(rèn)構(gòu)造或未初始化) |
bool isNull() const | 文檔是否無效(同 isEmpty(),部分版本差異可忽略) |
void swap(QJsonDocument&) | 交換兩個(gè)文檔的內(nèi)容(高效) |
三、與其他 QJson 類的協(xié)作
QJsonDocument是容器,需配合以下類完成完整的 JSON 處理:
類名 | 作用 |
|---|---|
QJsonValue | JSON 基本值的封裝(null/bool/int/double/string/object/array) |
QJsonObject | JSON 對(duì)象(鍵值對(duì)集合,類似 std::map<QString, QJsonValue>) |
QJsonArray | JSON 數(shù)組(有序值集合,類似 QList<QJsonValue>) |
QJsonParseError | 解析錯(cuò)誤的詳細(xì)信息(error枚舉+offset錯(cuò)誤位置) |
關(guān)系鏈:
QJsonDocument→ 包含 QJsonObject/QJsonArray→ 包含 QJsonValue→ 對(duì)應(yīng) JSON 基本類型。
四、實(shí)際場(chǎng)景應(yīng)用
用 ZynqMP + Qt 開發(fā),流媒體是核心方向。QJsonDocument可用于以下場(chǎng)景:
1. 流媒體配置管理
用 JSON 存儲(chǔ)設(shè)備的流媒體參數(shù)(如 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調(diào)整屏幕亮度。
2. 設(shè)備狀態(tài)上報(bào)
將監(jiān)視器的實(shí)時(shí)狀態(tài)(如播放狀態(tài)、碼率、溫度、剩余電量)封裝為 JSON,通過 HTTP/MQTT 上報(bào)到服務(wù)器。
示例狀態(tài) JSON:
{
"device_id": "PM-2024-001",
"timestamp": 1718236800,
"status": {
"play_state": "playing",
"bitrate": 2048,
"fps": 29.97,
"temperature": 45,
"battery": 80
}
}生成后:用 QNetworkAccessManager發(fā)送 POST 請(qǐng)求。
3. 固件/配置更新
通過 JSON 描述更新包的信息(版本號(hào)、下載地址、校驗(yàn)和),解析后觸發(fā) OTA 升級(jí)。
五、注意事項(xiàng)與常見問題
1. 編碼問題
JSON 標(biāo)準(zhǔn)要求UTF-8 編碼,QJsonDocument僅支持 UTF-8。若源數(shù)據(jù)是 GBK 等其他編碼,需先轉(zhuǎn)換為 UTF-8(用 QString::fromLocal8Bit()或 QTextCodec)。
2. 根元素限制
JSON 根必須是對(duì)象或數(shù)組,不能直接是字符串/數(shù)字。若要存儲(chǔ)單個(gè)值,需用對(duì)象包裝:
// 錯(cuò)誤:根是字符串
// QJsonDocument doc("hello");
// 正確:用對(duì)象包裝
QJsonObject obj;
obj["message"] = "hello";
QJsonDocument doc(obj);3. 錯(cuò)誤處理
解析前務(wù)必檢查 QJsonParseError:
常見錯(cuò)誤:QJsonParseError::IllegalValue(非法值)、QJsonParseError::MissingObject(缺少對(duì)象)、QJsonParseError::SyntaxError(語法錯(cuò)誤)。
4. 性能優(yōu)化
- 隱式共享:
QJsonDocument拷貝時(shí)是淺拷貝,修改時(shí)才深拷貝,避免不必要的內(nèi)存開銷; - 大文檔處理:若 JSON 文檔過大(如超過 10MB),建議用流式解析(Qt 未提供原生流式 API,可考慮第三方庫如
simdjson),但嵌入式場(chǎng)景下很少遇到。
5. 鍵不存在的處理
訪問 QJsonObject的不存在的鍵時(shí),返回無效的 QJsonValue(isUndefined()為 true)。需用以下方式安全取值:
QJsonObject obj = ...;
// 方法1:先判斷鍵存在
if (obj.contains("stream_url")) {
QString url = obj["stream_url"].toString();
}
// 方法2:用 value() 取默認(rèn)值
QString url = obj.value("stream_url").toString("rtsp://default.url");六、擴(kuò)展:QVariant 與 JSON 的轉(zhuǎn)換
QJsonDocument提供 fromVariant()/toVariant()方法,可將 QVariantMap(對(duì)應(yīng) JSON 對(duì)象)、QVariantList(對(duì)應(yīng) JSON 數(shù)組)與 JSON 互轉(zhuǎn),簡(jiǎn)化 Qt 數(shù)據(jù)結(jié)構(gòu)與 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();
總結(jié)
QJsonDocument是 Qt 處理 JSON 的核心入口,結(jié)合 QJsonObject/QJsonArray可輕松實(shí)現(xiàn) JSON 的解析與生成。
到此這篇關(guān)于Qt QJsonDocument 的使用小結(jié)的文章就介紹到這了,更多相關(guān)Qt QJsonDocument 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++?Boost?CircularBuffer算法超詳細(xì)精講
Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個(gè)可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱2022-11-11
Matlab實(shí)現(xiàn)三維投影繪制的示例代碼
這篇文章系小編為大家?guī)砹艘粋€(gè)三維投影繪制函數(shù)(三視圖繪制),函數(shù)支持三維曲線、曲面、三維多邊形、參數(shù)方程曲線、參數(shù)方程曲面的投影繪制,需要的可以參考一下2022-08-08
C++設(shè)計(jì)模式之策略模式(Strategy)
這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之策略模式Strategy ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
C語言隨機(jī)數(shù)生成教程(rand和srand用法)
這篇文章主要介紹了C語言隨機(jī)數(shù)生成教程(rand和srand用法),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
詳解C語言中的fopen()函數(shù)和fdopen()函數(shù)
這篇文章主要介紹了詳解C語言中的fopen()函數(shù)和fdopen()函數(shù),注意其之間指針功能相關(guān)的區(qū)別,需要的朋友可以參考下2015-08-08

