Qtの基礎 - JSON
概要
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ファイルを作成する場合、以下に示す手順に従う。
- まず、QJsonObjectクラスを使用して、JSONオブジェクトを作成する。
- 配列の場合は、QJsonArrayクラスを使用してJSON配列を作成した後、それをオブジェクトに追加する。
- 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ファイルを編集する場合、以下に示す手順に従う。
QFile
クラスを使用して、JSONファイルを読み込む。QJsonDocument
クラスを使用して読み込んだデータを解析して、JSONオブジェクトに変換する。QJsonObject
クラスでdescriptionキーの値を変更する。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ファイルの任意のオブジェクトを削除する場合、以下に示す手順に従う。
- JSONファイルの読み込み
QFile
クラスおよびQJsonDocument
クラスを使用して、JSONファイルを読み込む。
- "fuga"キーの値の確認
QJsonDocument
クラスを使用して読み込んだデータを解析する。- 各オブジェクトの"fuga"キーの値を確認して、値が"ff"と一致するものを特定する。
- 条件に一致するオブジェクトの削除
- 条件に一致するオブジェクトを配列から削除する。
- 変更をファイルに保存
- 変更後の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();
}