本文转载自豆子的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 文档,我们只需要使用下面的代码模板:
代码语言:javascript复制// 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 类库直接支持隐式数据共享,因此我们不需要为复制的效率担心。
下面是完整的测试代码:
代码语言:javascript复制#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();
testJson02();
testJson03();
return a.exec();
}
在Qt Creator中的输出结果如下图所示: