직렬화 변환기
서로 다른 직렬화 형식 간에 변환하는 방법.
이 예제는 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 (const Converter *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));
}
return EXIT_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 클래스도 있습니다. 이 클래스는 데이터 불러오기를 지원하지 않습니다. 출력 형식은 두 가지 옵션을 사용하여 구성할 수 있습니다. 하나는 (더 상세한) 확장 CBOR 진단 형식을 사용할지 여부를 선택하는 옵션입니다. 다른 하나는 각 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.