Qtの基礎 - JSON

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

QJsonDocumentクラスは、JSONドキュメントをラップするクラスである。
UTF-8でエンコードされたテキストベースの表現からJSONファイルを読み書きすることができる。

JSONファイルは、QJsonDocumentクラスのfromJsonメソッドを使用して、QJsonDocumentクラスに変換することができる。
JSONパーサーは高速で効率的であり、JSONをQtが使用するバイナリ表現に変換する。

解析されたJSONファイルの有効性は、isNullメソッドで照会することができる。

また、isArrayメソッドおよびisObjectメソッドを使用して、JSONファイルに配列やオブジェクトが含まれているかどうかを調べることができる。
JSONファイルに含まれる配列やオブジェクトをarrayメソッド、objectメソッドで取得して操作するしたりすることも可能である。


JSONの注意点

JSONの詳細を知りたい場合は、RFC 8259を参照すること。

文字のエスケープ

文字列の中でダブルクォーテーション、バックスラッシュを文字として扱う場合、\ (バックスラッシュ) を使用してエスケープする必要がある。

 #  : keyに\Sample "Word"\という文字列を入力する場合
 
 {
    "key" : "\\Sample \"Word\"\\"
 }


数値は10進数のみ扱うことができる

数値において、2進数、8進数、16進数を使用することはできない。

 # 間違った例 :
 
 {
    "value1" : 0xF0,
    "value2" : 070
 }



JSONファイルの読み込み

単一オブジェクトの場合

 # Sample.json
 
 {
    "appDesc": {
       "description": "SomeDescription",
       "message": "SomeMessage"
    },
 
    "appName": {
       "description": "Home",
       "message": "Welcome",
       "imp":["awesome","best","good"]
    }
 }


  • CMakeを使用する場合
 # Qt 5の場合
 find_package(Qt5 REQUIRED COMPONENTS Core)
 target_link_libraries(<プロジェクト名> PRIVATE Qt5::Core)
 
 # Qt 6の場合
 find_package(Qt6 REQUIRED COMPONENTS Core)
 target_link_libraries(<プロジェクト名> PRIVATE Qt6::Core)


  • QMakeを使用する場合
 QT += core


 #include <vector>
 #include <QJsonDocument>
 
 void readJson()
 {
    // Jsonファイルの読み込み
    QFile file("Sample.json");
    file.open(QIODevice::ReadOnly | QIODevice::Text);
 
    // valueの内容 : QJsonValue(object, QJsonObject({"description": "Home","imp": ["awesome","best","good"],"message": "YouTube"}) )
    QString value = file.readAll();
 
    file.close();
 
    QJsonDocument doc = QJsonDocument::fromJson(value.toUtf8());
    QJsonObject sett2 = doc.object();
 
    // appvalueの内容 : QJsonObject({"description": "Home","imp": ["awesome","best","good"],"message": "YouTube"}) 
    QJsonValue appvalue = sett2.value(QString("appName"));
 
    // itemの内容 : QJsonValue(string, "Home") 
    QJsonObject item = appvalue.toObject();
 
    // Jsonの値が文字列の場合、値を文字列に変換する
    QString subobj = item["description"].toString();
 
    // Jsonの値が配列の場合、配列を文字列に変換する
    QJsonArray impvalues = item["imp"].toArray();
 
    QString impvalue2 = impvalues[2].toString();  // 要素を指定して取得する場合
 
    std::vector<QString> vecvalues = {};
    for (const auto impvalue : impvalues) {       // 範囲ループforで取得する場合
       vecvalues.push_back(impvalue.toString());
    }
 }


配列オブジェクトの場合

 # Sample.json
 
 {
    {
       "description": "SomeDescription",
       "message": "SomeMessage"
    },
 
    {
       "description": "Home",
       "message": "Welcome",
       "imp":["awesome","best","good"]
    }
 }


 #include <QFile>
 #include <QJsonDocument>
 #include <QJsonArray>
 #include <QJsonObject>
 #include <QString>
 #include <QDebug>
 
 void readJson()
 {
    // Jsonファイルの読み込み
    QFile file("Sample.json");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "JSONファイルの読み込みに失敗しました" << filePath;
        return;
    }
 
    QByteArray jsonData = file.readAll();
 
    // ファイルを閉じる
    file.close();
 
    QJsonDocument document = QJsonDocument::fromJson(jsonData);
    if (!document.isArray()) {
       qDebug() << "JSONファイルに配列オブジェクトがありません";
       return;
    }
 
    QJsonArray jsonArray = document.array();
    foreach (const QJsonValue &value, jsonArray) {
       QJsonObject obj = value.toObject();
       QString desc    = obj["description"].toString();
       QString message = obj["message"].toString();
 
       // キーの値が配列の場合、配列を文字列に変換する
       QJsonArray impvalues = obj["imp"].toArray();
       // 配列から要素を指定して取得する場合
       QString impvalue1 = impvalues[1].toString();
 
       // ...略
    }
 }



JSONファイルの作成

JSONファイルを作成する場合、以下に示す手順に従う。

  1. まず、QJsonObjectクラスを使用して、JSONオブジェクトを作成する。
  2. 配列の場合は、QJsonArrayクラスを使用してJSON配列を作成した後、それをオブジェクトに追加する。
  3. QJsonDocumentクラスを使用してJSONドキュメントを作成した後、それをファイルに書き込む。


以下の例では、指定されたJSON構造を持つSample.jsonファイルを生成している。

QJsonDocumentクラスのtoJsonメソッドは、整形されていないJSONデータを返す。
読みやすい形式で出力する場合は、toJson(QJsonDocument::Indented)メソッドを使用すること。

 #include <QCoreApplication>
 #include <QFile>
 #include <QJsonDocument>
 #include <QJsonObject>
 #include <QJsonArray>
 #include <QException>
 #include <QDebug>
 
 
 int main(int argc, char *argv[])
 {
    QCoreApplication a(argc, argv);
 
    // JSONオブジェクトの作成
    QJsonObject jsonObject;
    jsonObject["description"] = "Home";
 
    // JSON配列を定義して値を追加する
    QJsonArray impArray;
    impArray.append("awesome");
    impArray.append("best");
    impArray.append("good");
 
    // 配列をオブジェクトに追加
    jsonObject["imp"] = impArray;
 
    // 別のキーと値を追加
    jsonObject["message"] = "YouTube";
 
    // JSONドキュメントを作成
    QJsonDocument jsonDocument(jsonObject);
 
    try {
       // JSONファイルを作成
       QFile file("Sample.json");
       if (!file.open(QIODevice::WriteOnly)) {
          qWarning("ファイルを開けませんでした。");
          return -1;
       }
 
       file.write(jsonDocument.toJson());
       file.close();
    }
    catch (QException &ex) {
       qWarning("Could not create json file : " + ex.what());
       return -1;
    }
 
    return a.exec();
 }


以下に示すようなJSONファイルが作成される。

 # Sample.json
 
 {
    "appDesc": {
       "description": "SomeDescription",
       "message": "SomeMessage"
    },
 
    "appName": {
       "description": "Home",
       "message": "Welcome",
       "imp":["awesome","best","good"]
    }
 }



JSONファイルの更新

以下に示すようなJSONファイルにおいて、appDescオブジェクトにあるdescriptionキーの値を変更する。

 # Sample.json
 
 {
    "appDesc": {
       "description": "SomeDescription",
       "message": "SomeMessage"
    },
 
    "appName": {
       "description": "Home",
       "message": "Welcome",
       "imp":["awesome","best","good"]
    }
 }


JSONファイルを編集する場合、以下に示す手順に従う。

  1. QFileクラスを使用して、JSONファイルを読み込む。
  2. QJsonDocumentクラスを使用して読み込んだデータを解析して、JSONオブジェクトに変換する。
  3. QJsonObjectクラスでdescriptionキーの値を変更する。
  4. QJsonDocumentクラスを使用して変更したJSONオブジェクトから新しいJSONドキュメントを作成して、それをファイルに書き込む。


以下の例では、Sample.jsonファイルからJSONデータを読み込み、appDesc内のdescriptionキーの値をhogeに変更して、同じファイルに変更を保存している。

 #include <QCoreApplication>
 #include <QFile>
 #include <QJsonDocument>
 #include <QJsonObject>
 #include <QException>
 #include <QDebug>
 
 
 int main(int argc, char *argv[])
 {
    QCoreApplication a(argc, argv);
 
    // Sample.josnファイルを開く
    QFile file("Sample.json");
    if (!file.open(QIODevice::ReadOnly)) {
       qWarning("Could not open json file.");
       return -1;
    }
 
    try {
       // Sample.jsonファイルからJSONデータを読み込む
       QByteArray jsonData = file.readAll();
    }
    catch (QException &ex) {
       qWarning("Could not read json file.");
       file.close();
 
       return -1;
    }
 
    file.close();
 
    // JSONドキュメントを解析
    QJsonDocument document = QJsonDocument::fromJson(jsonData);
    QJsonObject rootObject = document.object();
 
    // appDescオブジェクトを取得して、descriptionキーの値を変更
    QJsonObject appDescObject = rootObject["appDesc"].toObject();
    appDescObject["description"] = "hoge";  // descriptionキーの値を変更
 
    // 変更したappDescオブジェクトをrootオブジェクトに格納
    rootObject["appDesc"] = appDescObject;
 
    // 変更したappDescオブジェクトでJSONドキュメントを更新
    QJsonDocument updatedDocument(rootObject);
 
    // ファイルに書き出し
    if (!file.open(QIODevice::WriteOnly)) {
       qWarning("ファイルを再度開けませんでした。");
       return -1;
    }
 
    try {
       file.write(updatedDocument.toJson());
    }
    catch (QException &ex) {
       qWarning("Could not modify json file.");
       file.close();
 
       return -1;
    }
 
    file.close();
 
    return a.exec();
 }



JSONファイルのオブジェクトの削除

以下に示すようなJSONファイルにおいて、各オブジェクトからfugaキーの値がffのオブジェクトを削除する。

 [
    {
       "hoge": "aa",
       "piyo": "bb",
       "fuga": "cc"
    },
    {
    {
       "hoge": "dd",
       "piyo": "ee",
       "fuga": "ff"
    },
    {
       "hoge": "gg",
       "piyo": "hh",
       "fuga": "ii"
    }
 ]


JSONファイルの任意のオブジェクトを削除する場合、以下に示す手順に従う。

  1. JSONファイルの読み込み
    QFileクラスおよびQJsonDocumentクラスを使用して、JSONファイルを読み込む。
  2. "fuga"キーの値の確認
    QJsonDocumentクラスを使用して読み込んだデータを解析する。
    各オブジェクトの"fuga"キーの値を確認して、値が"ff"と一致するものを特定する。
  3. 条件に一致するオブジェクトの削除
    条件に一致するオブジェクトを配列から削除する。
  4. 変更をファイルに保存
    変更後のJSONデータをファイルに再保存する。


以下の例では、JSONファイルからデータを読み込み、各オブジェクトにあるfugaキーの値がffのオブジェクトを削除して、その結果を元のファイルに上書き保存している。

 #include <QCoreApplication>
 #include <QFile>
 #include <QJsonDocument>
 #include <QJsonArray>
 #include <QJsonObject>
 #include <QDebug>
 
 int main(int argc, char *argv[])
 {
    QCoreApplication a(argc, argv);
 
    QFile file("/path/to/your/jsonfile.json");
    if (!file.open(QIODevice::ReadOnly)) {
       qWarning("ファイルを開けませんでした。");
       return -1;
    }
 
    QByteArray data = file.readAll();
    QJsonDocument doc(QJsonDocument::fromJson(data));
    QJsonArray array = doc.array();
 
    // "fuga"キーの値が"ff"のオブジェクトを削除する
    QJsonArray newArray;
    QString targetfugaStr = "ff";

    for (int i = 0; i < array.size(); ++i) {
       QJsonObject obj = array[i].toObject();
       QString fugaString = obj["fuga"].toString()
       if (targetfugaStr != targetDate) {
          newArray.append(obj);
       }
    }
 
    // 変更をファイルに保存
    QJsonDocument saveDoc(newArray);
    if (!file.open(QIODevice::WriteOnly)) {
       qWarning("ファイルを書き込みモードで開けませんでした");
       return -1;
    }
 
    try {
       file.write(saveDoc.toJson());
    }
    catch (QException &ex) {
       qWarning("JSONファイルの保存に失敗しました");
       file.close();
 
       return -1;
    }
 
    file.close();
 
    return a.exec();
 }