シリアライゼーションコンバータ
異なるシリアライズ形式間の変換方法。
この例では、JSON、CBOR、XML、QDataStream 、およびいくつかの単純なテキスト形式間の変換を行います。使用されている形式を自動検出することも、使用する形式を指定することも可能です。 すべての形式が入力と出力の両方をサポートしているわけではなく、サポートするコンテンツのデータ型のセットも形式ごとに異なります。QDataStream とXMLが最も機能豊富で、次にCBOR、JSON、そしてプレーンテキスト形式の順となります。機能の限られた形式を介した変換では、データの構造が失われやすくなります。

Converter クラス
Converterクラスは、すべてのフォーマット間の変換を行うすべてのコンバータの抽象スーパークラスです。これらのコンバータはすべて、内部ですべてのデータ構造を表現するために使用されるQVariant クラスとの間で変換を行います。
class Converter
{
static QList<const Converter *> &converters();
protected:
Converter();
static bool isNull(const Converter *converter); // in nullconverter.cpp
public:
static const QList<const Converter *> &allConverters();
enum class Direction { In = 1, Out = 2, InOut = In | Out };
Q_DECLARE_FLAGS(Directions, Direction)
enum Option { SupportsArbitraryMapKeys = 0x01 };
Q_DECLARE_FLAGS(Options, Option)
virtual ~Converter() = 0;
virtual QString name() const = 0;
virtual Directions directions() const = 0;
virtual Options outputOptions() const;
virtual const char *optionsHelp() const;
virtual bool probeFile(QIODevice *f) const;
virtual QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const;
virtual void saveFile(QIODevice *f, const QVariant &contents,
const QStringList &options) const = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Directions)
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Options)Converterクラスのコンストラクタとデストラクタは、メインプログラムが利用可能なコンバータを把握できるよう、メインプログラムで使用される利用可能なコンバータのリストを管理します。各コンバータ型は、自身が確実に生成され、このリストを通じてメインプログラムから利用可能となるよう保証する静的インスタンスを定義しています。allConverters() メソッドは、main() のコードに対してこのリストへのアクセスを提供します。
Converter::Converter()
{
converters().append(this);
}
Converter::~Converter()
{
converters().removeAll(this);
}
QList<const Converter *> &Converter::converters()
{
Q_CONSTINIT static QList<const Converter *> store;
return store;
}
const QList<const Converter *> &Converter::allConverters()
{
return converters();
}name() 関数は、コンバータの名前を返します。directions() 関数は、コンバータが入力、出力、あるいはその両方に使用できるかどうかを判断するために使用されます。これらにより、メインプログラムは、入力および出力形式を選択するためのコマンドラインオプションのヘルプテキスト内で、利用可能なコンバータを報告できるようになります。
QStringList inputFormats;
QStringList outputFormats;
for (const Converter *conv : Converter::allConverters()) {
auto direction = conv->directions();
QString name = conv->name();
if (direction.testFlag(Converter::Direction::In))
inputFormats << name;
if (direction.testFlag(Converter::Direction::Out))
outputFormats << name;
}optionsHelp() 関数は、--format-options <format> というコマンドラインオプションを使用して問い合わせた際、利用可能なフォーマットでサポートされているさまざまなコマンドラインオプションを報告するために使用されます。
for(constConverter*conv: Converter::allConverters()) {
if(conv->name()==format) {
const char *help = conv->optionsHelp();
if(help) {
qInfo("The following options are available for format '%s':\n\n%s",
qPrintable(format), help);
}else{
qInfo("Format '%s' supports no options.", qPrintable(format));
}
returnEXIT_SUCCESS;
}
}outputOptions() 関数は、コンバータの出力機能を報告します。現時点では、唯一のオプション機能は、キーから値へのマッピングにおける任意のキーのサポートです。入力コンバータの loadFile() は、この情報を使用して、読み込んだデータを表示する形式を調整し、出力コンバータの機能の範囲内で、そのデータを可能な限り忠実に表現することができます。
probeFile() 関数は、ファイルがコンバータのフォーマットに一致するかどうかを判定するために使用されます。メインプログラムは、ユーザーがコマンドラインで使用するフォーマットを指定していない場合、ファイル名および場合によっては内容に基づいて、ファイルの読み込みや書き込みにどのフォーマットを使用するかを決定するために、この関数を使用します。
loadFile() 関数は、データの逆シリアライズを行います。 呼び出し元は、loadFile() に使用するシリアライザを指定します。これにより、loadFile() はそのシリアライザの outputOptions() を照会して、読み込まれたデータをどのような形式で表現するかを決定します。呼び出し元が出力コンバータの選択を決定していない場合、loadFile() は、返されるデータに適したデフォルトの出力コンバータを指定します。
saveFile() 関数はデータをシリアライズします。この関数には、loadHelp() で説明されているように、コマンドラインからオプションが渡され、ファイルへの保存時にデータをどのように表現するかの詳細を調整することができます。
loadFile() と saveFile() はどちらも、任意の `QIODevice` と共に使用できます。つまり、ネットワークソケットやその他のデータソースに対して読み書きを行う際にも、`Converter` を使用することが可能です。本プログラムでは、メインプログラムは常に `QFile` を渡しており、これによりディスク上のファイルまたはプロセスの標準ストリームのいずれかにアクセスします。
利用可能なコンバータ
いくつかのコンバータがサポートされており、必要に応じてコンバータプログラムを他のフォーマットに適応させる方法を示しています。 詳細については、各コンバータのソースコードを参照してください。CBOR コンバータは、コンバータの動作方法を比較的包括的に示す実例となっており、これについては後ほど詳しく見ていきます。以下の表は、利用可能なコンバータをまとめたものです:
| クラス | モード | フォーマット |
|---|---|---|
| CborConverter | 入力/出力 | CBOR |
| CborDiagnosticDumper | 出力 | CBOR 診断 |
| DataStreamConverter | 入力/出力 | QDataStream |
| デバッグ・テキスト・ダンパー | 出力 | ロスレス、非標準、人間が読みやすい形式 |
| JsonConverter | 入力/出力 | JSON |
| NullConverter | 出力 | 出力なし |
| TextConverter | 入力/出力 | 構造化されたプレーンテキスト |
| XmlConverter | 入力/出力 | XML |
入力をサポートするコンバータは、それ自体がloadFile()のフォールバックコンバータとして機能します。ただし、CBORおよびQDataStream コンバータは例外で、これらはそれぞれ対応する出力専用のダンプ用コンパニオンクラスを使用します。nullコンバータは、入力コンバータが実行する可能性のある検証や確認を行うためにプログラムを実行する際、出力コンバータとして使用できます。
CborConverter クラスおよび CborDiagnosticDumper クラス
CborConverterクラスは、CBOR形式へのシリアライズおよびCBOR形式からのデシリアライズをサポートしています。このクラスは、浮動小数点値の出力を設定するためのさまざまなオプションに加え、ファイルヘッダーとして機能し、そのファイルがCBORデータを含むことを識別するCBORタグで出力を開始するかどうかを決定するsignature オプションもサポートしています。
また、CBOR 診断表記で出力を行う CborDiagnosticDumper クラスもあります。このクラスはデータの読み込みには対応していません。出力の形式は 2 つのオプションを使用して設定できます。1 つは、(より詳細な)拡張 CBOR 診断形式を使用するかどうかを選択するものです。もう 1 つは、各 CBOR 値を別々の行に表示するかどうかを制御するものです。
プレーンな診断表記はJSONに似ていますが、完全に同一というわけではありません。これは、CBORストリームの内容をロスレスで表示できるのに対し、JSONへの変換ではデータが失われる可能性があるためです。CborConverterのloadFile()メソッドは、呼び出し元が出力形式を自ら指定していない場合、フォールバック出力コンバータとしてCborDiagnosticDumperを使用します。
convertCborValue()、convertCborMap()、およびconvertCborArray() ヘルパー関数は、CborConverter::loadFile() の処理を円滑にするために、QCborValue をQVariant に変換するために使用されます。
static QVariant convertCborValue(const QCborValue &value);
static QVariant convertCborMap(const QCborMap &map)
{
VariantOrderedMap result;
result.reserve(map.size());
for (auto pair : map)
result.append({ convertCborValue(pair.first), convertCborValue(pair.second) });
return QVariant::fromValue(result);
}
static QVariant convertCborArray(const QCborArray &array)
{
QVariantList result;
result.reserve(array.size());
for (auto value : array)
result.append(convertCborValue(value));
return result;
}
static QVariant convertCborValue(const QCborValue &value)
{
if (value.isArray())
return convertCborArray(value.toArray());
if (value.isMap())
return convertCborMap(value.toMap());
return value.toVariant();
}convertFromVariant() 関数は、いずれかのクラスのsaveFile() による出力のために、QVariant をQCborValue に変換するために使用されます。
enum TrimFloatingPoint { Double, Float, Float16 };
static QCborValue convertFromVariant(const QVariant &v, TrimFloatingPoint fpTrimming)
{
if (v.userType() == QMetaType::QVariantList) {
const QVariantList list = v.toList();
QCborArray array;
for (const QVariant &v : list)
array.append(convertFromVariant(v, fpTrimming));
return array;
}
if (v.userType() == qMetaTypeId<VariantOrderedMap>()) {
const auto m = qvariant_cast<VariantOrderedMap>(v);
QCborMap map;
for (const auto &pair : m)
map.insert(convertFromVariant(pair.first, fpTrimming),
convertFromVariant(pair.second, fpTrimming));
return map;
}
if (v.userType() == QMetaType::Double && fpTrimming != Double) {
float f = float(v.toDouble());
if (fpTrimming == Float16)
return float(qfloat16(f));
return f;
}
return QCborValue::fromVariant(v);
}convert プログラム
main() 関数は、QApplication およびQCommandLineParser を設定し、ユーザーが指定したオプションを適切に処理し、ユーザーが要求した場合はヘルプを提供します。この関数は、ユーザーの選択内容を記述する各種QCommandLineOption インスタンスから取得した値と、ファイル名用の位置引数を使用して、使用するコンバータを準備します。
その後、入力コンバータを使用してデータを読み込み(まだ出力コンバータが選択されていない場合は、その選択を決定することもあります)、出力コンバータを使用して、ユーザーがコマンドラインで指定した出力オプションを考慮しながら、そのデータをシリアル化します。
QStringList files = parser.positionalArguments();
QFile input(files.value(0));
QFile output(files.value(1));
const Converter *inconv = prepareConverter(parser.value(inputFormatOption),
Converter::Direction::In, &input);
const Converter *outconv = prepareConverter(parser.value(outputFormatOption),
Converter::Direction::Out, &output);
// Now finally perform the conversion:
QVariant data = inconv->loadFile(&input, outconv);
Q_ASSERT_X(outconv, "Serialization Converter",
"Internal error: converter format did not provide default");
outconv->saveFile(&output, data, parser.values(optionOption));
return EXIT_SUCCESS;「CBORデータの解析と表示」、「ゲームの保存と読み込み」、および「QtにおけるCBORのサポート」も参照してください 。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.