首页 > 解决方案 > 未从 QJsonObject 正确检索 QJsonArrays

问题描述

在我目前正在从事的项目中,我使用 Qt 的 JSON 功能来存储图形的状态,其中系统的每个组件都递归地调用toJson其成员的 -functions 以进行序列化。这很好用,但是在反序列化 JSON 文件时遇到了一个奇怪的问题。

作为说明问题的测试,我创建了以下示例代码:

#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtDebug>

int main() {
  auto document{QJsonDocument::fromJson("{\n"
                                        "  \"o1\" : {\n"
                                        "    \"i1\" : [\"l1\", \"l2\", \"l3\"],\n"
                                        "    \"i2\": 3.14\n"
                                        "  },\n"
                                        "  \"o2\" : {\n"
                                        "    \"i2\": 2.718,\n"
                                        "    \"i1\" : [\"l1\", \"l2\", \"l3\"]\n"
                                        "  }\n"
                                        "}")};
  qDebug() << "is the document an object:" << document.isObject();
  auto document_object{document.object()};

  auto object_1_value{document_object.value("o1")};
  qDebug() << "is o1 an object:" << object_1_value.isObject();
  auto object_1{object_1_value.toObject()};

  auto inner_1_value{object_1.value("i1")};
  qDebug() << "is i1 an array:" << inner_1_value.isArray();
  auto inner_1{inner_1_value.toArray()};
  qDebug() << "i1:" << inner_1;

  auto inner_1_inner_value{inner_1.at(0)};
  qDebug() << "is i1[0] an array:" << inner_1_inner_value.isArray();
  auto inner_1_inner{inner_1_inner_value.toArray()};
  qDebug() << "i1[0]:" << inner_1_inner;

  return 0;
}

在这里,我首先查询o1,然后尝试获取存储在 下的数组i1。但是,我得到以下输出:

is the document an object: true
is o1 an object: true
is i1 an array: true
i1: QJsonArray([["l1","l2","l3"]])
is i1[0] an array: true
i1[0]: QJsonArray([["l1","l2","l3"]])

似乎 Qt 将返回的数组存储到一个无用的单元素数组中;在我的其他代码中,at(0)解决了这个问题,但在这里即使这样也行不通。

如果有人能帮我找到一个解决方案,用 Qt 可靠地(最好是无破解地)读取嵌套的 JSON 数组,我会非常高兴,因为我真的不明白这个问题。我在带有 gcc 9.3.0 和 Qt 5.14.2 的 Linux 5.6.11 上。

标签: c++arraysjsonqtqt5

解决方案


您的问题是大括号初始化。当您改为进行赋值式初始化时,它会起作用。

// instead of
auto inner_1{inner_1_value.toArray()};
// use
auto inner_1 = inner_1_value.toArray();
// same for all other brace inits

我认为发生的是大括号初始化和通过std::initializer_list构造函数初始化列表之间的经典冲突,在这种情况下是这个:

QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args);

您想要大括号初始化 a QJsonArray,但std::initializer_list具有优先权,并且您实际实例化的是 a QJsonArray,其中一个项目又是 a QJsonArray

您经常会看到用std::vector<int>两个冲突的 ctor 来解释这个问题:

vector(size_type count);
vector(std::initializer_list<int> init);

推荐阅读