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



我目前使用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"
        }
    ]
}

这里我们有一个父QJsonObject包含一个键'CLOCKS'。该键的值是QJsonObjects的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,这是对值条目的引用…但是要实际访问this中的数据(如果值是另一个数组/对象),您必须使用toArray(), toObject()函数等进行转换。这个函数只返回副本,而不返回引用,这为使用引用沿着对象层次结构迭代设置了障碍。

到目前为止,我想到的唯一方法是创建整个"时钟"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对象层次结构,而不去所有这些努力!!

在浪费了我生命中的三个小时之后,我可以确认,到今天为止,这对于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"]等-您无法获得对aa["bb"]的引用,只能获得其值的副本。

什么是可能的,虽然是重新创建JSON与一个新的值添加,如下所述:https://forum.qt.io/topic/25096/modify-nested-qjsonvalue/4 -注意,这保持重新创建对象每次被调用,本质上是内存使用灾难,但这是所有Qt目前允许的。

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

Qt中目前包含的是一个"只读"实现来提供解析功能。他打算在未来用"参考"支持来扩展设计,但目前还没有完成。

我有一个类似的问题了几天,我已经设法找到了一个适合我的工作方法,我想我应该在这里分享一下。

您可以导航到希望更新其键值的对象。然后使用"remove"方法删除键值对,然后使用"insert"方法用新值重新插入。

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

值的就地更改是不支持的,因为我发现了困难的方式:)

相关内容

  • 没有找到相关文章

最新更新