20

現在、開発中のプログラムの一部のデータを処理するために、コア QJson ライブラリで Qt5.0 を使用しています。

この質問の場面を設定するために、私の問題を説明する 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 があります。このキーの値は、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 を取得できるという事実により、問題自体が明らかになりますが、実際にこの内部のデータにアクセスするには (値が別の配列/オブジェクトである場合)、toArray を使用して変換する必要があります。 ()、toObject() 関数など。この関数はコピーのみを返し、参照は返さず、参照を使用してオブジェクト階層を下に反復することへの障壁を作成します。

これを回避するためにこれまでに思いついた唯一の方法は、「CLOCKS」QJsonArray全体のコピーを作成し、必要なオブジェクトを見つけて削除し、変更されたデータで再挿入することです...そして最後に全体を割り当てます親オブジェクトの「CLOCKS」キーに配列を戻します。これは私にとっては面倒で、何か間違ったことをしているように感じ、もっと良い方法があるに違いありません。

これをサポートするために、これまでのコードは次のようになります...クロックQJsonObjectsの1つの「値」を変更するだけです:

  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 オブジェクト階層の単一の値を変更するためのより良い方法があるはずです!!!

4

3 に答える 3

16

私の人生の 3 時間を無駄にした後、今日の時点で、これは 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 で許可されているすべてです。

于 2015-03-31T05:24:44.653 に答える
11

実際にQt5でQJsonを書いたQt開発者からの情報によると -

現在 Qt に含まれているのは、解析機能を提供する「読み取り専用」の実装です。彼は、将来的に「参照」サポートでデザインを拡張するつもりですが、まだ完了していません。

于 2013-08-23T12:17:24.207 に答える