首页 > 编程语言 >Qt QJsonDocument使用小结

Qt QJsonDocument使用小结

来源:互联网 2026-07-16 06:58:13

QJsonDocument是Qt处理JSON的核心类,支持将JSON字符串解析为QJsonObject或QJsonArray,也可反向生成JSON。根元素须为对象或数组,采用隐式共享机制,性能高效。解析时需通过fromJson()传入UTF-8编码数据,并借助QJsonParseError检查错误,再用isObject()或isArray()确认根类型。

一、QJsonDocument 概述

在 Qt 中处理 JSON 数据,最核心的类就是 QJsonDocument。它属于 QtCore 模块,使用前需包含头文件 ,并在 .pro 文件中添加 QT += core。该类的主要职责如下:

Qt QJsonDocument使用小结

长期稳定更新的攒劲资源: >>>点此立即查看<<<

  • 解析:将 JSON 字符串或字节流转换为 Qt 可直接操作的结构化对象,如 QJsonObjectQJsonArray
  • 生成:将 QJsonObjectQJsonArray 转换回 JSON 字符串;
  • 封装:管理的 JSON 文档根元素必须是对象或数组,单个值不能直接作为根存在。

Qt JSON 模块采用轻量级设计,利用隐式共享(Implicitly Shared)机制,资源占用低、性能良好,特别适合嵌入式场景。

二、核心功能与用法

1. 解析 JSON(从字符串/字节流到 Qt 对象)

解析 JSON 字符串时,调用 QJsonDocument::fromJson() 静态方法即可。需要注意的是,传入数据必须是UTF-8 编码的 QByteArray。如果已有 QString,请先使用 toUtf8() 转换。

关键细节:

  • 错误处理:务必带上 QJsonParseError 参数,以便捕获解析错误——语法错误、非法字符等都能准确识别;
  • 根元素判断:解析完成后,使用 isObject()isArray() 确认根元素类型,再决定后续操作。

示例:解析 JSON 字符串

#include 
#include 
#include 
#include 

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 对象到字符串/字节流)

生成 JSON 的核心方法是 QJsonDocument::toJson(),支持两种输出格式:

  • QJsonDocument::Compact紧凑模式,无空格和换行,适合网络传输;
  • QJsonDocument::Indented缩进模式,带格式化排版,适合日志记录或调试查看。

示例:生成 JSON 配置

#include 
#include 
#include 
#include 

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 的核心方法和属性,方便快速参考:

方法/属性

说明

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 字节流,可选紧凑或缩进模式

bool isObject() const

判断根元素是否为对象

bool isArray() const

判断根元素是否为数组

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、对象或数组)

QJsonObject

对应 JSON 对象,即键值对集合,类似 std::map

QJsonArray

对应 JSON 数组,有序值集合,类似 QList

QJsonParseError

记录解析错误信息,包括错误类型枚举和出错偏移位置

它们之间的关系如下:

QJsonDocument 包含一个 QJsonObjectQJsonArray,而这两个类中存放的都是 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 升级流程。

五、注意事项与常见问题

初次接触 Qt JSON 模块时,需注意以下易错点。

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。不过在嵌入式场景中,遇到如此大体积 JSON 的概率较低。

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 其他基于 QVariant 的 API 交互:

// 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 数据时不可或缺的核心入口。掌握它,再配合 QJsonObjectQJsonArrayQJsonValue,无论是解析外部 JSON 配置,还是生成用于上报的数据结构,均可轻松实现。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。