上一章我们了解了如何使用 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 环境下进行编译运行。

    1. QString json("{"
    2. "\"encoding\" : \"UTF-8\","
    3. "\"plug-ins\" : ["
    4. "\"python\","
    5. "\"c++\","
    6. "\"ruby\""
    7. "],"
    8. "\"indent\" : { \"length\" : 3, \"use_space\" : true }"
    9. "}");
    10. QJsonParseError error;
    11. QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
    12. if (error.error == QJsonParseError::NoError) {
    13. if (jsonDocument.isObject()) {
    14. QVariantMap result = jsonDocument.toVariant().toMap();
    15. qDebug() << "encoding:" << result["encoding"].toString();
    16. qDebug() << "plugins:";
    17.  
    18. foreach (QVariant plugin, result["plug-ins"].toList()) {
    19. qDebug() << "\t-" << plugin.toString();
    20. }
    21.  
    22. QVariantMap nestedMap = result["indent"].toMap();
    23. qDebug() << "length:" << nestedMap["length"].toInt();
    24. qDebug() << "use_space:" << nestedMap["use_space"].toBool();
    25. }
    26. } else {
    27. qFatal(error.errorString().toUtf8().constData());
    28. exit(1);
    29. }

    这段代码与前面的几乎相同。QJsonDocument::fromJson()可以由QByteArray对象构造一个QJsonDocument对象,用于我们的读写操作。这里我们传入一个QJsonParseError对象的指针作为第二个参数,用于获取解析的结果。如果QJsonParseError::error()的返回值为QJsonParseError::NoError,说明一切正常,则继续以QVariant的格式进行解析(由于我们知道这是一个 JSON 对象,因此只判断了isObject()。当处理未知的 JSON 时,或许应当将所有的情况都考虑一边,包括isObject()isArray()以及isEmpty())。

    也就是说,如果需要使用QJsonDocument处理 JSON 文档,我们只需要使用下面的代码模板:

    1. // 1. 创建 QJsonParseError 对象,用来获取解析结果
    2. QJsonParseError error;
    3. // 2. 使用静态函数获取 QJsonDocument 对象
    4. QJsonDocument jsonDocument = QJsonDocument::fromJson(json.toUtf8(), &error);
    5. // 3. 根据解析结果进行处理
    6. if (error.error == QJsonParseError::NoError) {
    7. if (!(jsonDocument.isNull() || jsonDocument.isEmpty())) {
    8. if (jsonDocument.isObject()) {
    9. // ...
    10. } else if (jsonDocument.isArray()) {
    11. // ...
    12. }
    13. }
    14. } else {
    15. // 检查错误类型
    16. }

    QVariant对象生成 JSON 文档也很简单:

    1. QVariantList people;
    2.  
    3. QVariantMap bob;
    4. bob.insert("Name", "Bob");
    5. bob.insert("Phonenumber", 123);
    6.  
    7. QVariantMap alice;
    8. alice.insert("Name", "Alice");
    9. alice.insert("Phonenumber", 321);
    10.  
    11. people << bob << alice;
    12.  
    13. QJsonDocument jsonDocument = QJsonDocument::fromVariant(people);
    14. if (!jsonDocument.isNull()) {
    15. qDebug() << jsonDocument.toJson();
    16. }

    这里我们仍然使用的是QJsonDocument,只不过这次我们需要使用QJsonDocument::fromVariant()函数获取QJsonDocument对象。QJsonDocument也可以以二进制格式读取对象,比如QJsonDocument::fromBinaryData()QJsonDocument::fromRawData()函数。当我们成功获取到QJsonDocument对象之后,可以使用toJson()生成 JSON 文档。

    以上介绍了当我们有一个 JSON 文档时,如何使用QJsonDocument进行处理。如果我们没有 JSON 文档,那么我们可以使用QJsonDocumentsetArray()setObject()函数动态设置该对象,然后再生成对应的 JSON 格式文档。不过这部分需求比较罕见,因为我们直接可以从QVariant值类型获取。

    Qt5 提供的 JSON 类库直接支持隐式数据共享,因此我们不需要为复制的效率担心。