Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON
本文转载自 豆子 的Qt 学习之路2的博客 Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON
在C++中有不少 JSON 库,比如
- nlohmann/json JSON for Modern C++ 一款支持对结构体、Map、数组、vector等数据进行序列化和反序列化的现代C++的JSON解析库。
- RapidJson 腾讯开发的一款C++ JSON解析库,高效的 C++ JSON 解析/生成器,提供 SAX 及 DOM 风格 API
- QJson 基于Qt的Json解析库,适用于Qt4或者以上的版本。 关于JSON的C++解析库, https://www.json.org/json-en.html 中列出了不少,如下图所示:
本文直接使用Qt5中的使用
QJsonDocument
处理 JSON,关于
QJsonDocument
可以参考官方文档
QJsonDocument
上一章 Qt 学习之路 2(63):使用 QJson 处理 JSON 我们了解了如何使用 QJson 处理 JSON 文档。QJson 是一个基于 Qt 的第三方库,适用于 Qt4 和 Qt5 两个版本。不过,如果你的应用仅仅需要考虑兼容 Qt5,其实已经有了内置的处理函数。Qt5 新增加了处理 JSON 的类,与 XML 类库类似,均以 QJson 开头,在 QtCore 模块中,不需要额外引入其它模块。Qt5 新增加六个相关类:
类名 |
功能 |
---|---|
QJsonArray |
封装 JSON 数组 |
QJsonDocument |
读写 JSON 文档 |
QJsonObject |
封装 JSON 对象 |
QJsonObject::iterator |
用于遍历QJsonObject的 STL 风格的非 const 遍历器 |
QJsonParseError |
报告 JSON 处理过程中出现的错误 |
QJsonValue |
封装 JSON 值 |
我们还是使用前一章的 JSON 文档,这次换用
QJsonDocument
来解析。注意,
QJsonDocument
要求使用
Qt5
,本章中所有代码都必须在
Qt5
环境下进行编译运行。
QString json("{"
"\"encoding\" : \"UTF-8\","
"\"plug-ins\" : ["
"\"python\","
"\"c++\","
"\"ruby\""
"\"indent\" : { \"length\" : 3, \"use_space\" : true }"
"}");
QJsonParseError error;
QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
if (error.error == QJsonParseError::NoError) {
if (jsonDocument.isObject()) {
QVariantMap result = jsonDocument.toVariant().toMap();
qDebug() << "encoding:" << result["encoding"].toString();
qDebug() << "plugins:";
foreach (QVariant plugin, result["plug-ins"].toList()) {
qDebug() << "\t-" << plugin.toString();
QVariantMap nestedMap = result["indent"].toMap();
qDebug() << "length:" << nestedMap["length"].toInt();
qDebug() << "use_space:" << nestedMap["use_space"].toBool();
} else {
qFatal(error.errorString().toUtf8().constData());
exit(1);
}
这段代码与前面的几乎相同。
QJsonDocument::fromJson()
可以由
QByteArray
对象构造一个
JsonDocument对象
,用于我们的读写操作。这里我们传入一个
QJsonParseError
对象的指针作为第二个参数,用于获取解析的结果。如果
QJsonParseError::error()
的返回值为
QJsonParseError::NoError
,说明一切正常,则继续以
QVariant
的格式进行解析(由于我们知道这是一个
JSON
对象,因此只判断了
isObject()
。当处理未知的
JSON
时,或许应当将所有的情况都考虑一边,包括
isObject()
、
isArray()
以及
isEmpty()
)。
也就是说,如果需要使用QJsonDocument处理 JSON 文档,我们只需要使用下面的代码模板:
// 1. 创建 QJsonParseError 对象,用来获取解析结果
QJsonParseError error;
// 2. 使用静态函数获取 QJsonDocument 对象
QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
// 3. 根据解析结果进行处理
if (error.error == QJsonParseError::NoError) {
if (!(jsonDocument.isNull() || jsonDocument.isEmpty())) {
if (jsonDocument.isObject()) {
// ...
} else if (jsonDocument.isArray()) {
// ...
} else {
// 检查错误类型
}
将
QVariant
对象生成 JSON 文档也很简单:
QVariantList people;
QVariantMap bob;
bob.insert("Name", "Bob");
bob.insert("Phonenumber", 123);
QVariantMap alice;
alice.insert("Name", "Alice");
alice.insert("Phonenumber", 321);
people << bob << alice;
QJsonDocument jsonDocument = QJsonDocument::fromVariant(people);
if (!jsonDocument.isNull()) {
qDebug() << jsonDocument.toJson();
}
这里我们仍然使用的是
QJsonDocument
,只不过这次我们需要使用
QJsonDocument::fromVariant()
函数获取
QJsonDocument
对象。
QJsonDocument
也可以以二进制格式读取对象,比如
QJsonDocument::fromBinaryData()
和
QJsonDocument::fromRawData()
函数。当我们成功获取到
QJsonDocument
对象之后,可以使用
toJson()
生成 JSON 文档。
以上介绍了当我们有一个 JSON 文档时,如何使用
QJsonDocument
进行处理。如果我们没有 JSON 文档,那么我们可以使用
QJsonDocument
的
setArray()
和
setObject()
函数动态设置该对象,然后再生成对应的 JSON 格式文档。不过这部分需求比较罕见,因为我们直接可以从
QVariant
值类型获取。
Qt5 提供的 JSON 类库直接支持 隐式数据共享 ,因此我们不需要为复制的效率担心。
下面是完整的测试代码:
#include <QCoreApplication>
#include <QJsonObject>
#include <QJsonDocument>
#include <QByteArray>
#include <QDebug>
#include <QJsonParseError>
#include <QVariantMap>
#include <QVariant>
#include <QDebug>
void testJson01()
QJsonObject jo;
jo.insert("rip_file_path", "D://data/demo.prt");
QJsonObject joReq;
QJsonObject joContent;
joReq.insert("type", "select_rip_file");
joReq.insert("content", joContent);
QJsonObject jo1;
jo1.insert("request", joReq);
QJsonDocument doc;
doc.setObject(jo1);
QByteArray bResult = doc.toJson(QJsonDocument::Compact);
qDebug() << QString(bResult);
void testJson02()
QString json("{"
"\"encoding\": \"UTF-8\","
"\"plug-ins\": ["
"\"python\","
"\"java\","
"\"go\","
"\"C#\","
"\"C++\""
"\"indent\": {\"length\": 3, \"use_space\": true}"
"}");
QJsonParseError error;
QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
if (error.error == QJsonParseError::NoError)
if (!(jsonDocument.isNull() || jsonDocument.isEmpty())) {
if (jsonDocument.isObject())
QVariantMap resultMap = jsonDocument.toVariant().toMap();
qDebug() << "encoding:" << resultMap["encoding"].toString();
qDebug() << "plugins:";
foreach (QVariant plugin, resultMap["plug-ins"].toList())
qDebug() << "\t-" << plugin.toString();
QVariantMap nestedMap = resultMap["indent"].toMap();
qDebug() << "length:" << nestedMap["indent"].toInt();
qDebug() << "use_space:" << nestedMap["use_space"].toBool();
} else {
qFatal(error.errorString().toUtf8().constData());
exit(1);
void testJson03()
QVariantList people;
QVariantMap bob;
bob.insert("Name", "Bob");
bob.insert("Age", 32);
bob.insert("PhoneNumber", "18189076767");
QVariantMap alice;
alice.insert("Name", "Alice");
alice.insert("Age", 24);
alice.insert("PhoneNumber", "13789076767");
people << bob << alice;
QJsonDocument jsonDocument = QJsonDocument::fromVariant(people);
if (!jsonDocument.isNull()) {
QByteArray jsonByteA = jsonDocument.toJson();
QString strJson = jsonByteA.toStdString().c_str();
qDebug() << QString(strJson);
int main(int argc, char *argv[])
QCoreApplication a(argc, argv);
testJson01();