如何在不使用副本的情况下更改QJson层次结构中的QJsonObject值?

时间:2013-06-10 23:19:26

标签: c++ json qt qt5 qjson

我目前正在使用Qt5.0和核心QJson库来处理我正在开发的程序的一些数据。

要设置此问题的场景,我将为您提供一些说明我的问题的JSON数据:

{
    "CLOCKS": [
        {
            "ID": "clk",
            "MAX": 2e+08,
            "MIN": 1e+07,
            "VALUE": "no_clock"
        },
        {
            "ID": "memclk",
            "MAX": 2e+08,
            "MIN": 1e+07,
            "VALUE": "memclk"
        }
    ]
}

这里我们有一个包含单个键'CLOCKS'的父QJsonObject。此键的值是QJsonObject的QJsonArray,它包含许多包含我的数据的键/值对。

如果我想检索id为'clk'的QJsonObject,我目前正在使用这样的代码:

// imagine m_data is my parent QJsonObject
QJsonArray clocks = m_data["CLOCKS"].toArray();
foreach (const QJsonValue & value, clocks) {
    QJsonObject obj = value.toObject();
    if (obj["ID"].toString() == "clk") {
        return obj;
    }
}

这很好用,到目前为止图书馆一直很棒。但是,当我想获得一个QJsonObject 引用进行修改而不是复制时,我最近开始遇到问题。

所以我的问题是,给定样本数据提供了如何获取QJsonObject引用以修改所需时钟数据对象中的键/值对。问题表明,IMO由于你可以获得QJsonValueRefs,它是对值条目的引用...但实际访问其中的数据(如果值是另一个数组/对象),你必须使用toArray转换(),toObject()函数等。这个函数只返回副本而不是引用,创建了一个障碍,用引号迭代对象层次结构。

到目前为止我想出的唯一方法是创建整个“CLOCKS”QJsonArray的副本,找到我想要的对象然后将其删除并重新插入更改后的数据......最后将整个数组分配回父对象中的“CLOCKS”键。这对我来说似乎很麻烦,我觉得我做错了什么,必须有更好的方法。

这里支持这个是我的代码到目前为止的样子...只是改变其中一个时钟QJsonObjects的“VALUE”:

  QJsonArray resets = m_data.value(TAG_RESETS).toArray();

  // get a copy of the QJsonObject
  QJsonObject obj;
  foreach (const QJsonValue & value, resets) {
    QJsonObject o = value.toObject();
    if (o.value(TAG_ID).toString() == id) {
      obj = o;
      break;
    }
  }

  // modify the object
  obj[TAG_VALUE] = "NEW VALUE";

  // erase the old instance of the object
  for (auto it = resets.begin(); it != resets.end(); ++it) {
    QJsonObject obj = (*it).toObject();
    if (obj.value(TAG_ID).toString() == id) {
      resets.erase(it);

      // assign the array copy which has the object deleted
      m_data[TAG_RESETS] = resets;
      break;
    }
  }   

  // add the modified QJsonObject
  resets.append(obj);

  // replace the original array with the array containing our modified object
  m_data[TAG_RESETS] = resets;

我知道这可以缩短一点但是看起来似乎必须有一个更好的方法来更改QJson对象层次结构中的单个值而不需要付出所有这些努力!

3 个答案:

答案 0 :(得分:13)

在浪费了我三个小时的生命之后,我可以确认到目前为止,Qt 5.4仍然是不可能的。您可以修改JSON对象,但不能修改嵌套的JSON对象。

问题在于代码如:

json["aa"].toObject()["bb"] = 123;

基本上意味着以下内容:

QJsonObject temp = json["aa"].toObject();
temp["bb"] = 123;

并且由于temp不是引用而是对象(并且toObject()没有返回引用),因此编译但会被丢弃。

基本上它分解为这样一个事实:无法获得对刚刚创建的对象的引用,这意味着你无法从左到右创建它们,即aa [" bb"] - > aa [" bb"] [" cc"]等 - 您无法获得对[" bb"]的引用,只能获取其值的副本。

虽然可以使用添加的新值重新创建JSON,但如下所述:https://forum.qt.io/topic/25096/modify-nested-qjsonvalue/4 - 请注意,这会在每次调用时不断重新创建对象,并且本质上是内存使用灾难,但是这样是Qt目前所允许的。

答案 1 :(得分:9)

根据Qt开发人员在Qt5中实际编写QJson的信息 -

Qt目前包含的是一个“只读”实现,用于提供解析工具。他打算在未来扩展设计并提供“参考”支持,但尚未完成。

答案 2 :(得分:1)

几天来我遇到了类似的问题,并且设法找到了一种对我有效的解决方法,我想在此分享。

您可以导航到要更新其键值的对象。然后使用“删除”方法删除键值对,然后使用“插入”方法再次插入新值。

这可能会破坏键-值对在对象中的顺序,但是由于无论如何您都将通过键进行访问,因此这不成问题。

不支持就地更改值,因为我发现很难:)