Add JSON serialization and deserialization for Qt Protobuf

Also, move basic API for serializers into QProtobufBaseSerializer class

- add full basic types JSON serialization/deserialization functionality
- add list serialization/deserialization functionality

[ChangeLog][Protobuf] Edit existing QProtobufSerializer API,
also move serialization/deserialization methods from QProtobufSerializer
class into QProtobufBaseSerializer interface, since all
of them shall be re-usable for new Json-serializer.

Autotests cover: basic types and list serialization;
TBD:  maps, enums, Any type, OneOf, enumLists
will be completed in subsequent tasks

Pick-to: 6.7
Task-number: QTBUG-113731
Change-Id: I7556308062e8e576d32a371f3cb1d4f694824498
Reviewed-by: 🌴 Alexey Edelev 🌴 <alexey.edelev@qt.io>
This commit is contained in:
Tatiana Borisova 2023-11-24 18:07:30 +01:00 committed by Alexey Edelev
parent e6bc158296
commit 3c6e601bb9
18 changed files with 3171 additions and 354 deletions

View File

@ -5,11 +5,13 @@ qt_internal_add_module(Protobuf
SOURCES
qtprotobufglobal.h
qabstractprotobufserializer.cpp qabstractprotobufserializer.h
qprotobufbaseserializer.cpp qprotobufbaseserializer.h
qprotobufmessage.cpp qprotobufmessage.h qprotobufmessage_p.h
qprotobuflazymessagepointer.h
qprotobufobject.h
qprotobufselfcheckiterator.h
qprotobufserializer.cpp qprotobufserializer.h qprotobufserializer_p.h
qprotobufjsonserializer.cpp qprotobufjsonserializer.h
qtprotobuflogging.cpp qtprotobuflogging_p.h
qtprotobuftypes.cpp qtprotobuftypes.h
qprotobufoneof.cpp qprotobufoneof.h

View File

@ -0,0 +1,85 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qprotobufbaseserializer.h"
#include <QtProtobuf/qprotobufmessage.h>
QT_BEGIN_NAMESPACE
/*!
\class QProtobufBaseSerializer
\inmodule QtProtobuf
\since 6.7
\brief The QProtobufBaseSerializer class is an interface that represents
basic functions for serializing/deserializing objects, lists, and enums.
The QProtobufBaseSerializer class registers serializers/deserializers for
classes implementing a protobuf message, inheriting QProtobufMessage. These
classes are generated automatically, based on a .proto file, using the cmake
build macro qt6_add_protobuf or by running qtprotobufgen directly.
This class should be used as a base for specific serializers. The handlers
property contains all message-specific serializers and should be used while
serialization/deserialization. Inherited classes should reimplement scope of
virtual methods that used by registered message
serialization/deserialization functions.
*/
/*!
Destroys this QProtobufBaseSerializer.
*/
QProtobufBaseSerializer::~QProtobufBaseSerializer() = default;
/*!
\fn QByteArray QProtobufBaseSerializer::serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const
This function serializes a registered Protobuf message \a message
with defined \a ordering and \a fieldInfo, that is recognized
like an object, into a QByteArray. \a message must not be \nullptr.
\sa deserializeObject()
*/
/*!
\fn bool QProtobufBaseSerializer::deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const
This function deserializes a registered Protobuf message \a message
with defined \a ordering from the \a it iterator. \a message must not be \nullptr.
Returns \c true if deserialization was successful, otherwise \c false.
\sa serializeObject()
*/
/*!
\relates QProtobufBaseSerializer
\fn template<typename T> inline void qRegisterProtobufType()
Registers a Protobuf type \e T.
This function is normally called by generated code.
*/
/*!
\relates QProtobufBaseSerializer
\fn template<typename K, typename V> inline void qRegisterProtobufMapType();
Registers a Protobuf map type \c K and \c V.
\c V must be a QProtobufMessage.
This function is normally called by generated code.
*/
/*!
\relates QProtobufBaseSerializer
\fn template<typename T> inline void qRegisterProtobufEnumType();
Registers serializers for enumeration type \c T in QtProtobuf global
serializers registry.
This function is normally called by generated code.
*/
QT_END_NAMESPACE

View File

@ -0,0 +1,347 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROTOBUFSBASEERIALIZER_H
#define QPROTOBUFSBASEERIALIZER_H
#include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufselfcheckiterator.h>
#include <QtCore/QList>
#include <QtCore/QMetaObject>
#include <QtCore/QPair>
#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
class Q_PROTOBUF_EXPORT QProtobufBaseSerializer: public QAbstractProtobufSerializer
{
public:
enum Status {
Serialized = 0,
SerializationInProgress,
SerializationError
};
virtual ~QProtobufBaseSerializer();
virtual QByteArray
serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual bool deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual QByteArray
serializeListObject(const QList<const QProtobufMessage*> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual Status
deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual QByteArray
serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual Status deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual QByteArray
serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual QByteArray
serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const = 0;
virtual bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
virtual bool
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const = 0;
};
namespace QtProtobufPrivate {
using Serializer = void (*)(const QProtobufBaseSerializer *, const QVariant &,
const QProtobufPropertyOrderingInfo &, QByteArray &);
using Deserializer = void (*)(const QProtobufBaseSerializer *, QProtobufSelfcheckIterator &,
QVariant &);
/*!
\private
\brief SerializationHandlers contains set of objects that required for class
serialization/deserialization
*/
struct SerializationHandler
{
Serializer serializer = nullptr; /*!< serializer assigned to class */
Deserializer deserializer = nullptr; /*!< deserializer assigned to class */
};
extern Q_PROTOBUF_EXPORT SerializationHandler findHandler(QMetaType type);
extern Q_PROTOBUF_EXPORT void registerHandler(QMetaType type, const SerializationHandler &handlers);
/*!
\private
\brief default serializer template for type T that inherits from QProtobufMessage
*/
template<typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void serializeObject(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
buffer.append(serializer->serializeObject(value.value<T *>(), T::propertyOrdering, fieldInfo));
}
/*!
\private
\brief default serializer template for list of type T objects that inherits from QProtobufMessage
*/
template<typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeList(const QProtobufBaseSerializer *serializer, const QVariant &listValue,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<V> objList = listValue.value<QList<V>>();
QList<const QProtobufMessage*> messageList;
for (const auto &value : objList)
messageList.append(&value);
buffer.append(serializer->serializeListObject(messageList, V::propertyOrdering, fieldInfo));
}
/*!
\private
\brief default serializer template for map of key K, value V
*/
template<typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QHash<K, V> original = value.value<QHash<K, V>>();
QList<QPair<QVariant, QVariant>> variantContainer;
for (const auto &[k, v] : original.asKeyValueRange()) {
variantContainer.append(qMakePair(QVariant::fromValue<K>(k),
QVariant::fromValue<V>(v)));
}
buffer.append(serializer->serializeMapPair(variantContainer, fieldInfo));
}
/*!
\private
\brief default serializer template for map of type key K, value V. Specialization for V that
inherits from QProtobufMessage
*/
template<typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QHash<K, V> original = value.value<QHash<K, V>>();
QList<QPair<QVariant, QVariant>> variantContainer;
for (const auto &[k, v] : original.asKeyValueRange()) {
variantContainer.append(qMakePair(QVariant::fromValue<K>(k),
QVariant::fromValue<V *>(&v)));
}
buffer.append(serializer->serializeMapPair(variantContainer, fieldInfo));
}
/*!
\private
\brief default serializer template for enum types
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnum(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
buffer.append(serializer->serializeEnum(QtProtobuf::int64(value.value<T>()), fieldInfo));
}
/*!
\private
\brief default serializer template for enum list types
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnumList(const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList;
for (auto enumValue : value.value<QList<T>>()) {
intList.append(QtProtobuf::int64(enumValue));
}
buffer.append(serializer->serializeEnumList(intList, fieldInfo));
}
/*!
\private
\brief default deserializer template for type T that inherits from QProtobufMessage
*/
template<typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void deserializeObject(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &to)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
Q_ASSERT_X(to.isNull() || to.metaType() == QMetaType::fromType<T *>(),
"QProtobufBaseSerializer",
"Property should be either uninitialized or contain a valid pointer");
T *value = to.value<T *>();
if (value == nullptr) {
value = new T;
to = QVariant::fromValue<T *>(value);
}
serializer->deserializeObject(value, T::propertyOrdering, it);
}
/*!
\private
\brief default deserializer template for list of type T objects that inherits from QProtobufMessage
*/
template<typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeList(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
V newValue;
QProtobufBaseSerializer::Status result = QProtobufBaseSerializer::SerializationError;
do {
result = serializer->deserializeListObject(&newValue, V::propertyOrdering, it);
QList<V> list = previous.value<QList<V>>();
list.append(newValue);
previous.setValue(list);
} while (result == QProtobufBaseSerializer::SerializationInProgress);
}
/*!
\private
*
\brief default deserializer template for map of key K, value V
*/
template<typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QHash<K, V> out = previous.value<QHash<K, V>>();
QVariant key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V>(V());
if (serializer->deserializeMapPair(key, value, it) == QProtobufBaseSerializer::Serialized) {
out[key.value<K>()] = value.value<V>();
previous = QVariant::fromValue<QHash<K, V>>(out);
}
}
/*!
\private
*
\brief default deserializer template for map of type key K, value V. Specialization for V
that inherits from QProtobufMessage
*/
template<typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
auto out = previous.value<QHash<K, V>>();
QVariant key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V *>(nullptr);
if (serializer->deserializeMapPair(key, value, it) == QProtobufBaseSerializer::Serialized) {
const auto valuePtr = value.value<V *>();
out[key.value<K>()] = valuePtr ? *valuePtr : V();
previous = QVariant::fromValue<QHash<K, V>>(out);
}
}
/*!
\private
*
\brief default deserializer template for enum type T
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnum(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &to)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QtProtobuf::int64 intValue;
if (serializer->deserializeEnum(intValue, it))
to = QVariant::fromValue<T>(static_cast<T>(intValue._t));
}
/*!
\private
*
\brief default deserializer template for enumList type T
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnumList(const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufBaseSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList;
if (!serializer->deserializeEnumList(intList, it))
return;
QList<T> enumList = previous.value<QList<T>>();
for (auto intValue : intList)
enumList.append(static_cast<T>(intValue._t));
previous = QVariant::fromValue<QList<T>>(enumList);
}
} // namespace QtProtobufPrivate
template<typename T>
inline void qRegisterProtobufType()
{
T::registerTypes();
QtProtobufPrivate::registerOrdering(QMetaType::fromType<T>(), T::propertyOrdering);
QtProtobufPrivate::registerHandler(
QMetaType::fromType<T *>(),
{ QtProtobufPrivate::serializeObject<T>, QtProtobufPrivate::deserializeObject<T> });
QtProtobufPrivate::registerHandler(
QMetaType::fromType<QList<T>>(),
{ QtProtobufPrivate::serializeList<T>, QtProtobufPrivate::deserializeList<T> });
}
template<typename K, typename V>
inline void qRegisterProtobufMapType()
{
QtProtobufPrivate::registerHandler(
QMetaType::fromType<QHash<K, V>>(),
{ QtProtobufPrivate::serializeMap<K, V>, QtProtobufPrivate::deserializeMap<K, V> });
}
#ifdef Q_QDOC
template<typename T>
inline void qRegisterProtobufEnumType();
#else // !Q_QDOC
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
inline void qRegisterProtobufEnumType()
{
QtProtobufPrivate::registerHandler(
QMetaType::fromType<T>(),
{ QtProtobufPrivate::serializeEnum<T>, QtProtobufPrivate::deserializeEnum<T> });
QtProtobufPrivate::registerHandler(
QMetaType::fromType<QList<T>>(),
{ QtProtobufPrivate::serializeEnumList<T>, QtProtobufPrivate::deserializeEnumList<T> });
}
#endif // Q_QDOC
QT_END_NAMESPACE
#endif // QPROTOBUFSBASEERIALIZER_H

View File

@ -0,0 +1,679 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qprotobufjsonserializer.h"
#include "qprotobufserializer_p.h"
#include "qprotobufmessage_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <QtCore/QtGlobal>
#include <QtCore/QVariant>
#include <map>
#include <unordered_map>
QT_BEGIN_NAMESPACE
/*!
\class QProtobufJsonSerializer
\inmodule QtProtobuf
\since 6.7
\brief The QProtobufJsonSerializer class is interface that represents
basic functions for serialization/deserialization of QProtobufMessage
objects to Json.
\reentrant
The QProtobufJsonSerializer class registers serializers/deserializers for
classes implementing a protobuf message, inheriting QProtobufMessage. These
classes are generated automatically, based on a .proto file, using the cmake
build macro qt6_add_protobuf or by running qtprotobufgen directly.
*/
/*!
\fn QAbstractProtobufSerializer::DeserializationError QProtobufJsonSerializer::deserializationError() const
Returns the last deserialization error.
*/
/*!
\fn QString QProtobufJsonSerializer::deserializationErrorString() const
Returns a human-readable string describing the last deserialization error.
If there was no error, an empty string is returned.
*/
using namespace Qt::StringLiterals;
using namespace QtProtobufPrivate;
class QProtobufJsonSerializerPrivate final
{
Q_DISABLE_COPY_MOVE(QProtobufJsonSerializerPrivate)
public:
using Serializer = std::function<QByteArray(const QVariant&)>;
using Deserializer = std::function<QVariant(const QJsonValue&, bool &ok)>;
struct SerializationHandlers {
// serializer assigned to class
Serializer serializer;
// deserializer assigned to class
Deserializer deserializer;
};
// TBD Replace std::unordered_map to QHash
using SerializerRegistry = std::unordered_map<int/*metatypeid*/, SerializationHandlers>;
static QByteArray serializeFloat(const QVariant &propertyValue)
{
bool ok = false;
float value = propertyValue.toFloat(&ok);
if (!ok || qIsNaN(value)) {
return QByteArray("NaN");
}
return QByteArray::number(value, 'g', 7);
}
static QByteArray serializeDouble(const QVariant &propertyValue)
{
bool ok = false;
double value = propertyValue.toDouble(&ok);
if (!ok || qIsNaN(value)) {
return QByteArray("NaN");
}
return QByteArray::number(value, 'g', 14);
}
static QByteArray serializeString(const QVariant &propertyValue)
{
return '"' + propertyValue.toString().toUtf8() + '"';
}
static QByteArray serializeBytes(const QVariant &propertyValue) {
return QByteArray("\"") + propertyValue.toByteArray().toBase64() + "\"";
}
template<typename L>
static QByteArray serializeList(const QVariant &propertyValue)
{
L listValue = propertyValue.value<L>();
QByteArray result("[");
for (auto value : listValue) {
result += QByteArray::number(value) + ",";
}
//Remove trailing `,`
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
}
static QByteArray serializeBoolList(const QVariant &propertyValue)
{
QtProtobuf::boolList listValue = propertyValue.value<QtProtobuf::boolList>();
QByteArray result("[");
for (auto value : listValue) {
if (value)
result += QByteArray("true,");
else
result += QByteArray("false,");
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
}
static QByteArray serializeFloatList(const QVariant &propertyValue)
{
QtProtobuf::floatList listValue = propertyValue.value<QtProtobuf::floatList>();
QByteArray result("[");
for (auto value : listValue) {
if (qIsNaN(value))
return QByteArray("NaN");
result += QByteArray::number(value, 'g', 7) + ",";
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
}
static QByteArray serializeStringList(const QVariant &propertyValue)
{
QStringList listValue = propertyValue.value<QStringList>();
QByteArray result("[");
for (auto value : listValue) {
result += QByteArray("\"") + value.toUtf8() + "\",";
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
}
static QByteArray serializeBytesList(const QVariant &propertyValue)
{
QByteArrayList listValue = propertyValue.value<QByteArrayList>();
QByteArray result("[");
for (auto value : listValue) {
result += QByteArray("\"") + value.toBase64() + "\",";
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
}
static QByteArray serializeDoubleList(const QVariant &propertyValue)
{
QtProtobuf::doubleList listValue = propertyValue.value<QtProtobuf::doubleList>();
QByteArray result("[");
for (auto value : listValue) {
if (qIsNaN(value))
return QByteArray("NaN");
result += QByteArray::number(value, 'g', 14) + ",";
}
if (listValue.size() > 0) {
result.chop(1);
}
result += "]";
return result;
}
QProtobufJsonSerializerPrivate(QProtobufJsonSerializer *q)
: qPtr(q)
{
// TBD Change to assigning the result of a lambda to a static variable
if (handlers.empty()) {
handlers[qMetaTypeId<QtProtobuf::int32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt32};
handlers[qMetaTypeId<QtProtobuf::sfixed32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt32};
handlers[qMetaTypeId<QtProtobuf::sint32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt32};
handlers[qMetaTypeId<QtProtobuf::sint64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt64};
handlers[qMetaTypeId<QtProtobuf::int64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt64};
handlers[qMetaTypeId<QtProtobuf::sfixed64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeInt64};
handlers[qMetaTypeId<QtProtobuf::uint32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt32};
handlers[qMetaTypeId<QtProtobuf::fixed32>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt32};
handlers[qMetaTypeId<QtProtobuf::uint64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt64};
handlers[qMetaTypeId<QtProtobuf::fixed64>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeUInt64};
handlers[qMetaTypeId<bool>()]
= {{}, QProtobufJsonSerializerPrivate::deserializeBool};
handlers[QMetaType::Float] = {QProtobufJsonSerializerPrivate::serializeFloat,
QProtobufJsonSerializerPrivate::deserializeFloat};
handlers[QMetaType::Double] = {QProtobufJsonSerializerPrivate::serializeDouble,
QProtobufJsonSerializerPrivate::deserializeDouble};
handlers[QMetaType::QString]
= {QProtobufJsonSerializerPrivate::serializeString,
QProtobufJsonSerializerPrivate::deserializeString};
handlers[QMetaType::QByteArray]
= {QProtobufJsonSerializerPrivate::serializeBytes,
QProtobufJsonSerializerPrivate::deserializeByteArray};
handlers[qMetaTypeId<QtProtobuf::boolList>()]
= {QProtobufJsonSerializerPrivate::serializeBoolList,
QProtobufJsonSerializerPrivate::deserializeList<bool>};
handlers[qMetaTypeId<QtProtobuf::int32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::int32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::int32>};
handlers[qMetaTypeId<QtProtobuf::int64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::int64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::int64>};
handlers[qMetaTypeId<QtProtobuf::sint32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sint32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sint32>};
handlers[qMetaTypeId<QtProtobuf::sint64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sint64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sint64>};
handlers[qMetaTypeId<QtProtobuf::uint32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::uint32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::uint32>};
handlers[qMetaTypeId<QtProtobuf::uint64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::uint64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::uint64>};
handlers[qMetaTypeId<QtProtobuf::fixed32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::fixed32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::fixed32>};
handlers[qMetaTypeId<QtProtobuf::fixed64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::fixed64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::fixed64>};
handlers[qMetaTypeId<QtProtobuf::sfixed32List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sfixed32List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sfixed32>};
handlers[qMetaTypeId<QtProtobuf::sfixed64List>()]
= {QProtobufJsonSerializerPrivate::serializeList<QtProtobuf::sfixed64List>,
QProtobufJsonSerializerPrivate::deserializeList<QtProtobuf::sfixed64>};
handlers[qMetaTypeId<QtProtobuf::floatList>()]
= {QProtobufJsonSerializerPrivate::serializeFloatList,
QProtobufJsonSerializerPrivate::deserializeList<float>};
handlers[qMetaTypeId<QtProtobuf::doubleList>()]
= {QProtobufJsonSerializerPrivate::serializeDoubleList,
QProtobufJsonSerializerPrivate::deserializeList<double>};
handlers[qMetaTypeId<QStringList>()]
= {QProtobufJsonSerializerPrivate::serializeStringList,
QProtobufJsonSerializerPrivate::deserializeStringList};
handlers[qMetaTypeId<QByteArrayList>()]
= {QProtobufJsonSerializerPrivate::serializeBytesList,
QProtobufJsonSerializerPrivate::deserializeList<QByteArray>};
}
}
~QProtobufJsonSerializerPrivate() = default;
QByteArray serializeValue(const QVariant &propertyValue,
const QProtobufPropertyOrderingInfo &fieldInfo)
{
QByteArray buffer;
QMetaType metaType = propertyValue.metaType();
auto userType = propertyValue.userType();
if (metaType.id() == QMetaType::UnknownType) {
return {};
}
auto handler = QtProtobufPrivate::findHandler(metaType);
if (handler.serializer) {
handler.serializer(qPtr, propertyValue, fieldInfo, buffer);
} else {
auto handler = handlers.find(userType);
if (handler != handlers.end() && handler->second.serializer) {
buffer += handler->second.serializer(propertyValue);
} else {
buffer += propertyValue.toString().toUtf8();
}
}
return buffer;
}
QByteArray serializeProperty(const QVariant &propertyValue,
const QProtobufPropertyOrderingInfo &fieldInfo)
{
return QByteArray("\"")
+ QByteArrayView(fieldInfo.getJsonName())
+ QByteArray("\":") + serializeValue(propertyValue, fieldInfo);
}
QByteArray serializeObject(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering)
{
QByteArray result = "{";
// if a message is not initialized, just return empty { }
if (message) {
for (int index = 0; index < ordering.fieldCount(); ++index) {
int fieldIndex = ordering.getFieldNumber(index);
Q_ASSERT_X(fieldIndex < 536870912 && fieldIndex > 0,
"",
"fieldIndex is out of range");
QProtobufPropertyOrderingInfo fieldInfo(ordering, index);
QVariant propertyValue = message->property(fieldInfo);
result.append(serializeProperty(propertyValue, fieldInfo));
result.append(",");
}
result.chop(1);
}
result.append("}");
return result;
}
static QVariant deserializeInt32(const QJsonValue &value, bool &ok)
{
auto val = value.toInt();
ok = value.isDouble();
return QVariant::fromValue(val);
}
static QVariant deserializeUInt32(const QJsonValue &value, bool &ok)
{
auto val = value.toVariant().toUInt(&ok);
return QVariant::fromValue(val);
}
static QVariant deserializeInt64(const QJsonValue &value, bool &ok)
{
auto val = value.toVariant().toLongLong(&ok);
return QVariant::fromValue(val);
}
static QVariant deserializeUInt64(const QJsonValue &value, bool &ok)
{
auto val = value.toVariant().toULongLong(&ok);
return QVariant::fromValue(val);
}
static QVariant deserializeFloat(const QJsonValue &value, bool &ok)
{
QByteArray data = value.toVariant().toByteArray();
if (data == "NaN" || data == "Infinity" || data == "-Infinity") {
ok = true;
return QVariant(data);
}
auto val = data.toFloat(&ok);
return QVariant::fromValue(val);
}
static QVariant deserializeDouble(const QJsonValue &value, bool &ok)
{
QByteArray data = value.toVariant().toByteArray();
if (data == "NaN" || data == "Infinity" || data == "-Infinity") {
ok = true;
return QVariant(data);
}
auto val = data.toDouble(&ok);
return QVariant::fromValue(val);
}
static QVariant deserializeBool(const QJsonValue &value, bool &ok)
{
ok = value.isBool();
return (value.isBool()) ? QVariant(value.toBool()) : QVariant();
}
static QVariant deserializeString(const QJsonValue &value, bool &ok)
{
ok = value.isString();
return value.toString();
}
static QVariant deserializeByteArray(const QJsonValue &value, bool &ok)
{
QByteArray data = value.toVariant().toByteArray();
if (value.isString()) {
ok = true;
return QVariant::fromValue(QByteArray::fromBase64(data));
}
ok = false;
return QVariant();
}
template<typename T>
static QVariant deserializeList(const QJsonValue &value, bool &ok)
{
if (!value.isArray()) {
ok = false;
return QVariant();
}
ok = true;
QList<T> list;
QJsonArray array = value.toArray();
auto handler = handlers.find(qMetaTypeId<T>());
if (handler == handlers.end() || !handler->second.deserializer) {
qProtoWarning() << "Unable to deserialize simple type list."
"Could not find deserializer for type"
<< QMetaType::fromType<T>().name();
return QVariant::fromValue(list);
}
for (auto arrayValue : array) {
bool valueOk = false;
QVariant newValue = handler->second.deserializer(arrayValue, valueOk);
list.append(newValue.value<T>());
}
return QVariant::fromValue(list);
}
static QVariant deserializeStringList(const QJsonValue &value, bool &ok)
{
if (!value.isArray()) {
ok = false;
return QVariant();
}
QStringList list;
if (value.isArray()) {
QJsonArray array = value.toArray();
for (auto arrayValue : array) {
QVariant newValue = deserializeString(arrayValue, ok);
list.append(newValue.value<QString>());
}
}
return QVariant::fromValue(list);
}
QVariant deserializeValue(const QMetaType &metaType,
QProtobufSelfcheckIterator &it,
const QJsonValue &value,
bool &ok)
{
QVariant result;
auto handler = QtProtobufPrivate::findHandler(metaType);
if (handler.deserializer) {
handler.deserializer(qPtr, it, result);
ok = result.isValid();
} else {
auto handler = handlers.find(metaType.id());
if (handler != handlers.end() && handler->second.deserializer) {
result = handler->second.deserializer(value, ok);
} else {
QString error = QString::fromUtf8("No deserializer is registered for value %1")
.arg(QString::fromUtf8(metaType.name()));
setDeserializationError(
QAbstractProtobufSerializer::NoDeserializerError,
QCoreApplication::translate("QtProtobuf",
error.toUtf8().data()));
}
}
return result;
}
bool deserializeObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QByteArrayView data)
{
auto it = QProtobufSelfcheckIterator::fromView(data);
Q_ASSERT(it.isValid() && it.bytesLeft() > 0);
bool ok = false;
// TBD Try fromJson(QBAView) instead of current variant
QJsonDocument document
= QJsonDocument::fromJson(QByteArray(data.data(), static_cast<size_t>(data.size())));
if (!document.isObject())
return false;
std::map<QString, QProtobufPropertyOrderingInfo> msgContainer; // map<key, fieldInfo>
for (int index = 0; index < ordering.fieldCount(); ++index) {
int fieldIndex = ordering.getFieldNumber(index);
Q_ASSERT_X(fieldIndex < 536870912 && fieldIndex > 0, "", "fieldIndex is out of range");
QProtobufPropertyOrderingInfo fieldInfo(ordering, index);
QString key = fieldInfo.getJsonName().toString();
msgContainer.insert(std::pair<QString, QProtobufPropertyOrderingInfo>(key, fieldInfo));
}
QByteArray object;
// Go through QJSON doc and find keys that are presented in msgContainer
QJsonObject obj = document.object();
for (auto &key : obj.keys()) {
QJsonValue jsonValue = obj.value(key);
auto iter = msgContainer.find(key);
if (iter != msgContainer.end()) {
QVariant newPropertyValue = message->property(iter->second);
// Complex message case; move iterator to the deserializing array
if (jsonValue.isArray()) {
QJsonArray array = jsonValue.toArray();
object = QJsonDocument(array).toJson();
it = QProtobufSelfcheckIterator::fromView(object);
}
// Complex message case; move iterator to the deserializing object
if (jsonValue.isObject()) {
object = QJsonDocument(jsonValue.toObject()).toJson();
it = QProtobufSelfcheckIterator::fromView(object);
}
newPropertyValue = deserializeValue(newPropertyValue.metaType(),
it,
jsonValue,
ok);
if (ok) {
message->setProperty(iter->second, std::move(newPropertyValue));
}
}
}
return ok;
}
void setDeserializationError(QAbstractProtobufSerializer::DeserializationError error,
const QString &errorString)
{
deserializationError = error;
deserializationErrorString = errorString;
}
void setUnexpectedEndOfStreamError()
{
setDeserializationError(QAbstractProtobufSerializer::UnexpectedEndOfStreamError,
QCoreApplication::translate("QtProtobuf",
"Unexpected end of stream"));
}
void clearError();
QAbstractProtobufSerializer::DeserializationError deserializationError =
QAbstractProtobufSerializer::NoDeserializerError;
QString deserializationErrorString;
QJsonArray activeArray;
private:
static SerializerRegistry handlers;
QProtobufJsonSerializer *qPtr;
};
QProtobufJsonSerializerPrivate::SerializerRegistry QProtobufJsonSerializerPrivate::handlers = {};
void QProtobufJsonSerializerPrivate::clearError()
{
deserializationError = QAbstractProtobufSerializer::NoError;
deserializationErrorString.clear();
}
QProtobufJsonSerializer::QProtobufJsonSerializer() :
d_ptr(new QProtobufJsonSerializerPrivate(this))
{
}
QProtobufJsonSerializer::~QProtobufJsonSerializer() = default;
QAbstractProtobufSerializer::DeserializationError
QProtobufJsonSerializer::deserializationError() const
{
return d_ptr->deserializationError;
}
QString QProtobufJsonSerializer::deserializationErrorString() const
{
return d_ptr->deserializationErrorString;
}
QByteArray
QProtobufJsonSerializer::serializeMessage(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering) const
{
return d_ptr->serializeObject(message, ordering);
}
bool QProtobufJsonSerializer::deserializeMessage(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QByteArrayView data) const
{
d_ptr->clearError();
auto it = QProtobufSelfcheckIterator::fromView(data);
if (!d_ptr->deserializeObject(message, ordering, data))
return false;
if (!it.isValid())
d_ptr->setUnexpectedEndOfStreamError();
return it.isValid();
}
QByteArray
QProtobufJsonSerializer::serializeObject(const QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
Q_UNUSED(fieldInfo);
return serializeMessage(message, ordering);
}
QByteArray
QProtobufJsonSerializer::serializeListObject(const QList<const QProtobufMessage*> &messageList,
const QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
QByteArray result("[");
for (auto message : messageList) {
result.append(serializeObject(message, ordering, fieldInfo) + ",");
}
if (messageList.size() > 0) {
result.chop(1);
}
result.append("]");
return result;
}
bool QProtobufJsonSerializer::deserializeObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
{
return deserializeMessage(message, ordering, it.data());
}
QProtobufBaseSerializer::Status
QProtobufJsonSerializer::deserializeListObject(QProtobufMessage *message,
const QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
{
if (d_ptr->activeArray.empty()) {
QJsonDocument doc = QJsonDocument::fromJson(QByteArray(it.data(), it.bytesLeft()));
if (doc.isArray())
d_ptr->activeArray = doc.array();
else
return QProtobufBaseSerializer::SerializationError;
}
// doc.array() is empty
if (d_ptr->activeArray.empty())
return QProtobufBaseSerializer::SerializationError;
const QJsonValue &element = d_ptr->activeArray.takeAt(0);
if (element.isObject()) {
auto newIt
= QProtobufSelfcheckIterator::fromView(QJsonDocument(element.toObject()).toJson());
bool result = deserializeObject(message, ordering, newIt);
if (!d_ptr->activeArray.empty()) {
return QProtobufBaseSerializer::SerializationInProgress;
} else {
return result ? QProtobufBaseSerializer::Serialized
: QProtobufBaseSerializer::SerializationError;
}
}
return QProtobufBaseSerializer::SerializationError;
}
QByteArray QProtobufJsonSerializer::serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
const QProtobufPropertyOrderingInfo &fieldInfo
) const
{
Q_UNUSED(fieldInfo);
QByteArray result;
for (auto element: list) {
const QVariant &key = element.first;
qProtoWarning() << "Map pair serialization will be done soon:" << key << element.second;
}
return result;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,113 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPROTOBUFJSONSERIALIZER_H
#define QPROTOBUFJSONSERIALIZER_H
#include <QtProtobuf/qtprotobufglobal.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <QtProtobuf/qprotobufbaseserializer.h>
#include <QtCore/QMetaObject>
QT_BEGIN_NAMESPACE
class QProtobufJsonSerializerPrivate;
class Q_PROTOBUF_EXPORT QProtobufJsonSerializer : public QProtobufBaseSerializer
{
Q_DISABLE_COPY_MOVE(QProtobufJsonSerializer)
public:
QProtobufJsonSerializer();
~QProtobufJsonSerializer() override;
QAbstractProtobufSerializer::DeserializationError deserializationError() const override;
QString deserializationErrorString() const override;
QByteArray serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering
) const override;
bool deserializeMessage(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const override;
QByteArray serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
bool deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
QByteArray
serializeListObject(const QList<const QProtobufMessage *> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status
deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
QByteArray
serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status
deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override
{
Q_UNUSED(key);
Q_UNUSED(value);
Q_UNUSED(it);
return QProtobufBaseSerializer::SerializationError;
}
QByteArray
serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const override
{
Q_UNUSED(value);
Q_UNUSED(fieldInfo);
return QByteArray();
}
QByteArray
serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override
{
Q_UNUSED(value);
Q_UNUSED(fieldInfo);
return QByteArray();
}
Q_REQUIRED_RESULT
bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override
{
Q_UNUSED(value);
Q_UNUSED(it);
return false;
}
Q_REQUIRED_RESULT bool
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override
{
Q_UNUSED(value);
Q_UNUSED(it);
return false;
}
private:
std::unique_ptr<QProtobufJsonSerializerPrivate> d_ptr;
};
QT_END_NAMESPACE
#endif // QPROTOBUFJSONSERIALIZER_H

View File

@ -62,8 +62,9 @@ private:
friend class QProtobufSerializer;
friend class QAbstractProtobufSerializer;
friend class QProtobufBaseSerializer;
friend class QProtobufSerializerPrivate;
friend class QAbstractProtobufSerializer;
friend class QProtobufJsonSerializerPrivate;
friend struct QProtobufMessageDeleter;
QProtobufMessagePrivate *d_ptr;

View File

@ -13,6 +13,7 @@
#include <QtCore/qvariant.h>
#include <QtCore/qreadwritelock.h>
#include <QtProtobuf/qprotobufmessage.h>
#include <QtProtobuf/private/qprotobufserializer_p.h>
#include <QtProtobuf/private/qprotobufmessage_p.h>
@ -99,33 +100,6 @@ QtProtobufPrivate::SerializationHandler QtProtobufPrivate::findHandler(QMetaType
If there was no error, an empty string is returned.
*/
/*!
\relates QProtobufSerializer
\fn template<typename T> inline void qRegisterProtobufType()
Registers a Protobuf type \e T.
This function is normally called by generated code.
*/
/*!
\relates QProtobufSerializer
\fn template<typename K, typename V> inline void qRegisterProtobufMapType();
Registers a Protobuf map type \c K and \c V.
\c V must be a QProtobufMessage.
This function is normally called by generated code.
*/
/*!
\relates QProtobufSerializer
\fn template<typename T> inline void qRegisterProtobufEnumType();
Registers serializers for enumeration type \c T in QtProtobuf global
serializers registry.
This function is normally called by generated code.
*/
using namespace Qt::StringLiterals;
using namespace QtProtobufPrivate;
@ -386,66 +360,81 @@ bool QProtobufSerializer::deserializeObject(QProtobufMessage *message,
}
/*!
This function is called to serialize \a message as a part of list property
This function is called to serialize \a messageList as a list of messages one by one
with \a ordering and \a fieldInfo.
You should not call this function directly.
*/
QByteArray QProtobufSerializer::serializeListObject(
const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
const QList<const QProtobufMessage*> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
return serializeObject(message, ordering, fieldInfo);
QByteArray result;
for (const auto &message : messageList)
result.append(serializeObject(message, ordering, fieldInfo));
return result;
}
/*!
This function deserializes an \a message from byte stream as part of list property, with
\a ordering from a QProtobufSelfcheckIterator \a it.
Returns \c true if deserialization was successful, otherwise \c false.
Returns \c Serialized if deserialization was successful,
otherwise \c SerializationError.
You should not call this function directly.
*/
bool QProtobufSerializer::deserializeListObject(QProtobufMessage *message,
QProtobufBaseSerializer::Status QProtobufSerializer::deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QProtobufSelfcheckIterator &it) const
{
return deserializeObject(message, ordering, it);
if (deserializeObject(message, ordering, it))
return QProtobufBaseSerializer::Serialized;
else
return QProtobufBaseSerializer::SerializationError;
}
/*!
This function serializes QMap pair of \a key and \a value with
This function serializes \a list of pairs, each pair has a key and a value with
\a fieldInfo to a QByteArray
You should not call this function directly.
*/
QByteArray
QProtobufSerializer::serializeMapPair(const QVariant &key, const QVariant &value,
QProtobufSerializer::serializeMapPair(const QList<QPair<QVariant, QVariant>> &list,
const QProtobufPropertyOrderingInfo &fieldInfo) const
{
auto keyHandler = findIntegratedTypeHandler(key.metaType(), false);
Q_ASSERT_X(keyHandler, "QProtobufSerializer", "Map key is not an integrated type.");
QByteArray result;
for (const auto &element : list) {
const QVariant &key = element.first;
auto keyHandler = findIntegratedTypeHandler(key.metaType(), false);
Q_ASSERT_X(keyHandler, "QProtobufSerializer", "Map key is not an integrated type.");
QByteArray result = QProtobufSerializerPrivate::encodeHeader(
fieldInfo.getFieldNumber(), QtProtobuf::WireTypes::LengthDelimited);
result.append(QProtobufSerializerPrivate::encodeHeader(
fieldInfo.getFieldNumber(), QtProtobuf::WireTypes::LengthDelimited));
result.append(QProtobufSerializerPrivate::prependLengthDelimitedSize(
result.append(QProtobufSerializerPrivate::prependLengthDelimitedSize(
keyHandler->serializer(
key, QProtobufSerializerPrivate::encodeHeader(1, keyHandler->wireType))
+ d_ptr->serializeProperty(value, fieldInfo.infoForMapValue())));
key, QProtobufSerializerPrivate::encodeHeader(1, keyHandler->wireType))
+ d_ptr->serializeProperty(element.second, fieldInfo.infoForMapValue())));
}
return result;
}
/*!
This function deserializes QMap pair of \a key and \a value from a
QProtobufSelfcheckIterator \a it.
Returns \c true if deserialization was successful, otherwise \c false.
Returns \c Serialized if deserialization was successful,
otherwise \c SerializationError.
You should not call this function directly.
*/
bool QProtobufSerializer::deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it) const
QProtobufBaseSerializer::Status QProtobufSerializer::deserializeMapPair(QVariant &key, QVariant &value, QProtobufSelfcheckIterator &it) const
{
return d_ptr->deserializeMapPair(key, value, it);
if (d_ptr->deserializeMapPair(key, value, it))
return QProtobufBaseSerializer::Serialized;
else
return QProtobufBaseSerializer::SerializationError;
}
/*!
@ -742,10 +731,12 @@ bool QProtobufSerializerPrivate::deserializeProperty(
auto handler = QtProtobufPrivate::findHandler(metaType);
if (!handler.deserializer) {
qProtoWarning() << "No deserializer for type" << metaType.name();
QString error
= QString::fromUtf8("No deserializer is registered for type %1")
.arg(QString::fromUtf8(metaType.name()));
setDeserializationError(
QAbstractProtobufSerializer::NoDeserializerError,
QCoreApplication::translate("QtProtobuf",
"No deserializer is registered for type %1"));
QCoreApplication::translate("QtProtobuf", error.toUtf8().data()));
return false;
}
handler.deserializer(q_ptr, it, newPropertyValue);

View File

@ -6,15 +6,9 @@
#define QPROTOBUFSERIALIZER_H
#include <QtProtobuf/qtprotobufglobal.h>
#include <QtProtobuf/qabstractprotobufserializer.h>
#include <QtProtobuf/qprotobufbaseserializer.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <QtProtobuf/QProtobufMessage>
#include <QtCore/QVariant>
#include <QtCore/QMetaObject>
#include <functional>
#include <memory>
@ -24,8 +18,9 @@ namespace QtProtobufPrivate {
class QProtobufSelfcheckIterator;
} // namespace QtProtobufPrivate
class QProtobufMessage;
class QProtobufSerializerPrivate;
class Q_PROTOBUF_EXPORT QProtobufSerializer : public QAbstractProtobufSerializer
class Q_PROTOBUF_EXPORT QProtobufSerializer : public QProtobufBaseSerializer
{
Q_DISABLE_COPY_MOVE(QProtobufSerializer)
public:
@ -37,7 +32,8 @@ public:
QByteArray
serializeMessage(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering) const override;
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering
) const override;
bool deserializeMessage(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QByteArrayView data) const override;
@ -45,311 +41,50 @@ public:
QByteArray
serializeObject(const QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
bool deserializeObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const;
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
QByteArray
serializeListObject(const QProtobufMessage *message,
serializeListObject(const QList<const QProtobufMessage *> &messageList,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const;
bool deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status deserializeListObject(QProtobufMessage *message,
const QtProtobufPrivate::QProtobufPropertyOrdering &ordering,
QtProtobufPrivate::QProtobufSelfcheckIterator &it
) const override;
QByteArray
serializeMapPair(const QVariant &key, const QVariant &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const;
bool deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const;
serializeMapPair(const QList<QPair<QVariant, QVariant> > &list,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QProtobufBaseSerializer::Status deserializeMapPair(QVariant &key, QVariant &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it
) const override;
QByteArray
serializeEnum(QtProtobuf::int64 value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
QByteArray
serializeEnumList(const QList<QtProtobuf::int64> &value,
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo) const;
const QtProtobufPrivate::QProtobufPropertyOrderingInfo &fieldInfo
) const override;
Q_REQUIRED_RESULT
bool deserializeEnum(QtProtobuf::int64 &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const;
Q_REQUIRED_RESULT
bool deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const;
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
Q_REQUIRED_RESULT bool
deserializeEnumList(QList<QtProtobuf::int64> &value,
QtProtobufPrivate::QProtobufSelfcheckIterator &it) const override;
void shouldPreserveUnknownFields(bool preserveUnknownFields);
private:
std::unique_ptr<QProtobufSerializerPrivate> d_ptr;
};
namespace QtProtobufPrivate {
using Serializer = void (*)(const QProtobufSerializer *, const QVariant &,
const QProtobufPropertyOrderingInfo &, QByteArray &);
using Deserializer = void (*)(const QProtobufSerializer *, QProtobufSelfcheckIterator &,
QVariant &);
/*!
\private
\brief SerializationHandlers contains set of objects that required for class
serialization/deserialization
*/
struct SerializationHandler
{
Serializer serializer = nullptr; /*!< serializer assigned to class */
Deserializer deserializer = nullptr; /*!< deserializer assigned to class */
};
extern Q_PROTOBUF_EXPORT SerializationHandler findHandler(QMetaType type);
extern Q_PROTOBUF_EXPORT void registerHandler(QMetaType type, const SerializationHandler &handlers);
/*!
\private
\brief default serializer template for type T that inherits from QProtobufMessage
*/
template<typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void serializeObject(const QProtobufSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
buffer.append(serializer->serializeObject(value.value<T *>(), T::propertyOrdering, fieldInfo));
}
/*!
\private
\brief default serializer template for list of type T objects that inherits from QProtobufMessage
*/
template<typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeList(const QProtobufSerializer *serializer, const QVariant &listValue,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
for (const auto &value : listValue.value<QList<V>>()) {
buffer.append(serializer->serializeListObject(&value, V::propertyOrdering, fieldInfo));
}
}
/*!
\private
\brief default serializer template for map of key K, value V
*/
template<typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
for (const auto &[k, v] : value.value<QHash<K, V>>().asKeyValueRange()) {
buffer.append(serializer->serializeMapPair(QVariant::fromValue<K>(k),
QVariant::fromValue<V>(v), fieldInfo));
}
}
/*!
\private
\brief default serializer template for map of type key K, value V. Specialization for V that
inherits from QProtobufMessage
*/
template<typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void serializeMap(const QProtobufSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
for (const auto &[k, v] : value.value<QHash<K, V>>().asKeyValueRange()) {
buffer.append(serializer->serializeMapPair(QVariant::fromValue<K>(k),
QVariant::fromValue<V *>(&v), fieldInfo));
}
}
/*!
\private
\brief default serializer template for enum types
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnum(const QProtobufSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
buffer.append(serializer->serializeEnum(QtProtobuf::int64(value.value<T>()), fieldInfo));
}
/*!
\private
\brief default serializer template for enum list types
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void serializeEnumList(const QProtobufSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &buffer)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList;
for (auto enumValue : value.value<QList<T>>()) {
intList.append(QtProtobuf::int64(enumValue));
}
buffer.append(serializer->serializeEnumList(intList, fieldInfo));
}
/*!
\private
\brief default deserializer template for type T that inherits from QProtobufMessage
*/
template<typename T,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, T>::value, int> = 0>
void deserializeObject(const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &to)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
Q_ASSERT_X(to.isNull() || to.metaType() == QMetaType::fromType<T *>(), "QProtobufSerializer",
"Property should be either uninitialized or contain a valid pointer");
T *value = to.value<T *>();
if (value == nullptr) {
value = new T;
to = QVariant::fromValue<T *>(value);
}
serializer->deserializeObject(value, T::propertyOrdering, it);
}
/*!
\private
\brief default deserializer template for list of type T objects that inherits from QProtobufMessage
*/
template<typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeList(const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
V newValue;
if (serializer->deserializeListObject(&newValue, V::propertyOrdering, it)) {
QList<V> list = previous.value<QList<V>>();
list.append(newValue);
previous.setValue(list);
}
}
/*!
\private
*
\brief default deserializer template for map of key K, value V
*/
template<typename K, typename V,
typename std::enable_if_t<!std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QHash<K, V> out = previous.value<QHash<K, V>>();
QVariant key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V>(V());
if (serializer->deserializeMapPair(key, value, it)) {
out[key.value<K>()] = value.value<V>();
previous = QVariant::fromValue<QHash<K, V>>(out);
}
}
/*!
\private
*
\brief default deserializer template for map of type key K, value V. Specialization for V
that inherits from QProtobufMessage
*/
template<typename K, typename V,
typename std::enable_if_t<std::is_base_of<QProtobufMessage, V>::value, int> = 0>
void deserializeMap(const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
auto out = previous.value<QHash<K, V>>();
QVariant key = QVariant::fromValue<K>(K());
QVariant value = QVariant::fromValue<V *>(nullptr);
if (serializer->deserializeMapPair(key, value, it)) {
const auto valuePtr = value.value<V *>();
out[key.value<K>()] = valuePtr ? *valuePtr : V();
previous = QVariant::fromValue<QHash<K, V>>(out);
}
}
/*!
\private
*
\brief default deserializer template for enum type T
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnum(const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &to)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QtProtobuf::int64 intValue;
if (serializer->deserializeEnum(intValue, it))
to = QVariant::fromValue<T>(static_cast<T>(intValue._t));
}
/*!
\private
*
\brief default deserializer template for enumList type T
*/
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
void deserializeEnumList(const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &previous)
{
Q_ASSERT_X(serializer != nullptr, "QProtobufSerializer", "Serializer is null");
QList<QtProtobuf::int64> intList;
if (!serializer->deserializeEnumList(intList, it))
return;
QList<T> enumList = previous.value<QList<T>>();
for (auto intValue : intList)
enumList.append(static_cast<T>(intValue._t));
previous = QVariant::fromValue<QList<T>>(enumList);
}
} // namespace QtProtobufPrivate
template<typename T>
inline void qRegisterProtobufType()
{
T::registerTypes();
QtProtobufPrivate::registerOrdering(QMetaType::fromType<T>(), T::propertyOrdering);
QtProtobufPrivate::registerHandler(
QMetaType::fromType<T *>(),
{ QtProtobufPrivate::serializeObject<T>, QtProtobufPrivate::deserializeObject<T> });
QtProtobufPrivate::registerHandler(
QMetaType::fromType<QList<T>>(),
{ QtProtobufPrivate::serializeList<T>, QtProtobufPrivate::deserializeList<T> });
}
template<typename K, typename V>
inline void qRegisterProtobufMapType()
{
QtProtobufPrivate::registerHandler(
QMetaType::fromType<QHash<K, V>>(),
{ QtProtobufPrivate::serializeMap<K, V>, QtProtobufPrivate::deserializeMap<K, V> });
}
#ifdef Q_QDOC
template<typename T>
inline void qRegisterProtobufEnumType();
#else // !Q_QDOC
template<typename T, typename std::enable_if_t<std::is_enum<T>::value, int> = 0>
inline void qRegisterProtobufEnumType()
{
QtProtobufPrivate::registerHandler(
QMetaType::fromType<T>(),
{ QtProtobufPrivate::serializeEnum<T>, QtProtobufPrivate::deserializeEnum<T> });
QtProtobufPrivate::registerHandler(
QMetaType::fromType<QList<T>>(),
{ QtProtobufPrivate::serializeEnumList<T>, QtProtobufPrivate::deserializeEnumList<T> });
}
#endif // Q_QDOC
QT_END_NAMESPACE
#endif // QPROTOBUFSERIALIZER_H

View File

@ -41,7 +41,7 @@ void registerQtTypeHandler()
{
registerHandler(
QMetaType::fromType<QType>(),
{ [](const QProtobufSerializer *serializer, const QVariant &value,
{ [](const QProtobufBaseSerializer *serializer, const QVariant &value,
const QProtobufPropertyOrderingInfo &info, QByteArray &buffer) {
auto do_convert = [](const QType &qtype) {
auto res = convert(qtype);
@ -60,7 +60,7 @@ void registerQtTypeHandler()
warnTypeConversionError();
}
},
[](const QProtobufSerializer *serializer, QProtobufSelfcheckIterator &it,
[](const QProtobufBaseSerializer *serializer, QProtobufSelfcheckIterator &it,
QVariant &value) {
PType object;
serializer->deserializeObject(&object, PType::propertyOrdering, it);

View File

@ -24,7 +24,7 @@ public:
static AnyPrivate *get(const Any *any) { return any->d_ptr; }
};
static void serializerProxy(const QProtobufSerializer *serializer, const QVariant &object,
static void serializerProxy(const QProtobufBaseSerializer *serializer, const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &output)
{
if (object.isNull())
@ -41,20 +41,31 @@ static void serializerProxy(const QProtobufSerializer *serializer, const QVarian
fieldInfo));
}
static void listSerializerProxy(const QProtobufSerializer *serializer, const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo, QByteArray &output)
static void listSerializerProxy(const QProtobufBaseSerializer *serializer,
const QVariant &object,
const QProtobufPropertyOrderingInfo &fieldInfo,
QByteArray &output)
{
const auto anyList = object.value<QList<Any>>();
const QList<Any> anyList = object.value<QList<Any>>();
QList<const QProtobufMessage*> msgList;
msgList.reserve(anyList.size());
QList<google::protobuf::Any> msgAny;
msgAny.reserve(anyList.size());
for (const Any &any : anyList) {
google::protobuf::Any realAny;
realAny.setValue(any.value());
realAny.setTypeUrl(any.typeUrl());
output.append(serializer->serializeListObject(&realAny,
google::protobuf::Any::propertyOrdering, fieldInfo));
msgAny.append(realAny);
}
for (const google::protobuf::Any &any : msgAny) {
msgList.append(&any);
}
output.append(serializer->serializeListObject(msgList,
google::protobuf::Any::propertyOrdering,
fieldInfo));
}
static void listDeserializerProxy(const QProtobufSerializer *deserializer,
static void listDeserializerProxy(const QProtobufBaseSerializer *deserializer,
QProtobufSelfcheckIterator &it, QVariant &object)
{
auto anyList = object.value<QList<Any>>();
@ -71,7 +82,7 @@ static void listDeserializerProxy(const QProtobufSerializer *deserializer,
object.setValue(std::move(anyList));
}
static void deserializerProxy(const QProtobufSerializer *deserializer,
static void deserializerProxy(const QProtobufBaseSerializer *deserializer,
QProtobufSelfcheckIterator &it, QVariant &object)
{
google::protobuf::Any realAny;

View File

@ -6,6 +6,7 @@ if(TARGET Qt6::qtprotobufgen)
get_target_property(protoc_version WrapProtoc::WrapProtoc _qt_internal_protobuf_version)
add_subdirectory(basic)
add_subdirectory(jsontypes)
add_subdirectory(syntax)
add_subdirectory(nopackage)
add_subdirectory(enums)

View File

@ -0,0 +1,2 @@
[RepeatedComplexMessageTest]
macos

View File

@ -0,0 +1,92 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_protobuf_json_basic LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
qt6_add_protobuf(tst_protobuf_json_basic_types_gen
PROTO_FILES
../basic/proto/basicmessages.proto
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated"
)
qt_autogen_tools_initial_setup(tst_protobuf_json_basic_types_gen)
qt_internal_add_test(tst_protobuf_json_basic_types
SOURCES
tst_protobuf_serialization_json_basictypes.cpp
LIBRARIES
Qt::Test
Qt::Protobuf
tst_protobuf_json_basic_types_gen
)
qt_internal_add_test(tst_protobuf_deserialization_json_basictypes
SOURCES
tst_protobuf_deserialization_json_basictypes.cpp
LIBRARIES
Qt::Test
Qt::Protobuf
tst_protobuf_json_basic_types_gen
)
qt6_add_protobuf(tst_protobuf_json_repeatedtypes_gen
PROTO_FILES
../basic/proto/repeatedmessages.proto
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated"
)
target_link_libraries(tst_protobuf_json_repeatedtypes_gen
PUBLIC
tst_protobuf_json_basic_types_gen
)
qt_autogen_tools_initial_setup(tst_protobuf_json_repeatedtypes_gen)
qt_internal_add_test(tst_protobuf_serialization_json_repeatedtypes
SOURCES
tst_protobuf_serialization_json_repeatedtypes.cpp
LIBRARIES
Qt::Test
Qt::Protobuf
tst_protobuf_json_basic_types_gen
tst_protobuf_json_repeatedtypes_gen
)
qt_internal_add_test(tst_protobuf_deserialization_json_repeatedtypes
SOURCES
tst_protobuf_deserialization_json_repeatedtypes.cpp
LIBRARIES
Qt::Test
Qt::Protobuf
tst_protobuf_json_basic_types_gen
tst_protobuf_json_repeatedtypes_gen
)
qt6_add_protobuf(tst_protobuf_json_maptypes_gen
PROTO_FILES
../basic/proto/mapmessages.proto
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_generated"
)
if(MINGW)
target_compile_options(tst_protobuf_json_maptypes_gen PRIVATE "-Wa,-mbig-obj")
endif()
qt_autogen_tools_initial_setup(tst_protobuf_json_maptypes_gen)
target_link_libraries(tst_protobuf_json_maptypes_gen
PUBLIC
tst_protobuf_json_basic_types_gen
)
qt_internal_add_test(tst_protobuf_serialization_json_maptypes
SOURCES
tst_protobuf_serialization_json_maptypes.cpp
INCLUDE_DIRECTORIES
../shared
LIBRARIES
Qt::Test
Qt::Protobuf
tst_protobuf_json_basic_types_gen
tst_protobuf_json_maptypes_gen
)

View File

@ -0,0 +1,494 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "basicmessages.qpb.h"
#include <QObject>
#include <QProtobufJsonSerializer>
#include <QTest>
using namespace Qt::Literals::StringLiterals;
class QtProtobufTypesJsonDeserializationTest : public QObject
{
Q_OBJECT
private slots:
void init() { qRegisterProtobufTypes(); serializer.reset(new QProtobufJsonSerializer); }
void BoolMessageDeserializeTest_data();
void BoolMessageDeserializeTest();
void IntMessageDeserializeTest_data();
void IntMessageDeserializeTest();
void UIntMessageDeserializeTest_data();
void UIntMessageDeserializeTest();
void SIntMessageDeserializeTest_data();
void SIntMessageDeserializeTest();
void Int64MessageDeserializeTest_data();
void Int64MessageDeserializeTest();
void UInt64MessageDeserializeTest_data();
void UInt64MessageDeserializeTest();
void SInt64MessageDeserializeTest_data();
void SInt64MessageDeserializeTest();
void FixedInt32MessageDeserializeTest_data();
void FixedInt32MessageDeserializeTest();
void FixedInt64MessageDeserializeTest_data();
void FixedInt64MessageDeserializeTest();
void SFixedInt32MessageDeserializeTest_data();
void SFixedInt32MessageDeserializeTest();
void SFixedInt64MessageDeserializeTest_data();
void SFixedInt64MessageDeserializeTest();
void FloatMessageDeserializeTest_data();
void FloatMessageDeserializeTest();
void DoubleMessageDeserializeTest_data();
void DoubleMessageDeserializeTest();
void StringMessageDeserializeTest();
void ComplexTypeDeserializeTest_data();
void ComplexTypeDeserializeTest();
void ResetComplexTypeDeserializeTest_data();
void ResetComplexTypeDeserializeTest();
void DefaultConstructedComplexTypeDeserializeTest();
void EmptyBytesMessageTest();
void EmptyStringMessageTest();
private:
std::unique_ptr<QProtobufJsonSerializer> serializer;
};
using namespace qtprotobufnamespace::tests;
void QtProtobufTypesJsonDeserializationTest::BoolMessageDeserializeTest_data()
{
QTest::addColumn<bool>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("True") << true << "{\"testFieldBool\":true}"_ba;
QTest::newRow("False") << false << "{\"testFieldBool\":false}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::BoolMessageDeserializeTest()
{
QFETCH(const bool, value);
QFETCH(const QByteArray, serializeData);
SimpleBoolMessage test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldBool(), value);
}
void QtProtobufTypesJsonDeserializationTest::IntMessageDeserializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("555") << 555 << "{\"testFieldInt\":555}"_ba;
QTest::newRow("0") << 0 << "{\"testFieldInt\":0}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::IntMessageDeserializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const QByteArray, serializeData);
SimpleIntMessage test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), value);
}
void QtProtobufTypesJsonDeserializationTest::UIntMessageDeserializeTest_data()
{
QTest::addColumn<uint32_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (uint32_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint32_t)65545 << "{\"testFieldInt\":65545}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::UIntMessageDeserializeTest()
{
QFETCH(const uint32_t, value);
QFETCH(const QByteArray, serializeData);
SimpleUIntMessage test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), value);
}
void QtProtobufTypesJsonDeserializationTest::SIntMessageDeserializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (int32_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int32_t)65545 << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int32_t)-1 << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int32_t)-63585 << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::SIntMessageDeserializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const QByteArray, serializeData);
SimpleSIntMessage test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), value);
}
void QtProtobufTypesJsonDeserializationTest::Int64MessageDeserializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (int64_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int64_t)-1 << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::Int64MessageDeserializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const QByteArray, serializeData);
SimpleInt64Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), value);
}
void QtProtobufTypesJsonDeserializationTest::UInt64MessageDeserializeTest_data()
{
QTest::addColumn<uint64_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (uint64_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint64_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint64_t)65545 << "{\"testFieldInt\":65545}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::UInt64MessageDeserializeTest()
{
QFETCH(const QtProtobuf::uint64, value);
QFETCH(const QByteArray, serializeData);
SimpleUInt64Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), value);
}
void QtProtobufTypesJsonDeserializationTest::SInt64MessageDeserializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (int64_t)15 << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int64_t)-1 << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::SInt64MessageDeserializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const QByteArray, serializeData);
SimpleSInt64Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), value);
}
void QtProtobufTypesJsonDeserializationTest::FixedInt32MessageDeserializeTest_data()
{
QTest::addColumn<uint32_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (uint32_t)15 << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545") << (uint32_t)65545 << "{\"testFieldFixedInt32\":65545}"_ba;
QTest::newRow("5") << (uint32_t)5 << "{\"testFieldFixedInt32\": 5}"_ba;
QTest::newRow("0") << (uint32_t)0 << "{\"testFieldFixedInt32\": 0}"_ba;
QTest::newRow("555") << (uint32_t)555 << "{\"testFieldFixedInt32\":555}"_ba;
QTest::newRow("nullptr") << (uint32_t)0 << "{\"testFieldFixedInt32\":null}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::FixedInt32MessageDeserializeTest()
{
QFETCH(const uint32_t, value);
QFETCH(const QByteArray, serializeData);
SimpleFixedInt32Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldFixedInt32(), value);
}
void QtProtobufTypesJsonDeserializationTest::FixedInt64MessageDeserializeTest_data()
{
QTest::addColumn<uint64_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (uint64_t)15 << "{\"testFieldFixedInt64\":15}"_ba;
QTest::newRow("300") << (uint64_t)300 << "{\"testFieldFixedInt64\":300}"_ba;
QTest::newRow("65545") << (uint64_t)65545 << "{\"testFieldFixedInt64\":65545}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::FixedInt64MessageDeserializeTest()
{
QFETCH(const uint64_t, value);
QFETCH(const QByteArray, serializeData);
SimpleFixedInt64Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldFixedInt64(), value);
}
void QtProtobufTypesJsonDeserializationTest::SFixedInt32MessageDeserializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (int32_t)15 << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545") << (int32_t)65545 << "{\"testFieldFixedInt32\":65545}"_ba;
QTest::newRow("-1") << (int32_t)-1 << "{\"testFieldFixedInt32\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << "{\"testFieldFixedInt32\":-462}"_ba;
QTest::newRow("-63585") << (int32_t)-63585 << "{\"testFieldFixedInt32\":-63585}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::SFixedInt32MessageDeserializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const QByteArray, serializeData);
SimpleSFixedInt32Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldFixedInt32(), value);
}
void QtProtobufTypesJsonDeserializationTest::SFixedInt64MessageDeserializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("15") << (int64_t)15 << "{\"testFieldFixedInt64\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << "{\"testFieldFixedInt64\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << "{\"testFieldFixedInt64\":65545}"_ba;
QTest::newRow("-1") << (int64_t)-1 << "{\"testFieldFixedInt64\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << "{\"testFieldFixedInt64\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << "{\"testFieldFixedInt64\":-63585}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::SFixedInt64MessageDeserializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const QByteArray, serializeData);
SimpleSFixedInt64Message test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldFixedInt64(), value);
}
void QtProtobufTypesJsonDeserializationTest::FloatMessageDeserializeTest_data()
{
QTest::addColumn<float>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("float_value_0_1") << 0.1f << "{\"testFieldFloat\":0.1}"_ba;
QTest::newRow("float_value_min") << std::numeric_limits<float>::min()
<< "{\"testFieldFloat\":1.17549e-38}"_ba;
QTest::newRow("float_value_max") << std::numeric_limits<float>::max()
<< "{\"testFieldFloat\":3.40282e+38}"_ba;
QTest::newRow("float_neg_value_4_2") << -4.2f << "{\"testFieldFloat\":-4.2}"_ba;
QTest::newRow("float_neg_value_0_0") << (float)-0.0f << "{\"testFieldFloat\":0}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::FloatMessageDeserializeTest()
{
QFETCH(const float, value);
QFETCH(const QByteArray, serializeData);
SimpleFloatMessage test;
test.setTestFieldFloat(value);
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldFloat(), value);
}
void QtProtobufTypesJsonDeserializationTest::DoubleMessageDeserializeTest_data()
{
QTest::addColumn<double>("value");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("double_value_0_1") << 0.1 << "{\"testFieldDouble\":0.1}"_ba;
QTest::newRow("double_value_min")
<< std::numeric_limits<double>::min()
<< "{\"testFieldDouble\":2.2250738585072014e-308}"_ba;
QTest::newRow("double_value_max")
<< std::numeric_limits<double>::max()
<< "{\"testFieldDouble\":1.7976931348623157e+308}"_ba;
QTest::newRow("double_neg_value_4_2") << -4.2
<< "{\"testFieldDouble\":-4.2}"_ba;
QTest::newRow("double_value_0_0") << 0.0 << "{\"testFieldDouble\":0}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::DoubleMessageDeserializeTest()
{
QFETCH(const double, value);
QFETCH(const QByteArray, serializeData);
SimpleDoubleMessage test;
test.setTestFieldDouble(value);
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldDouble(), value);
}
void QtProtobufTypesJsonDeserializationTest::StringMessageDeserializeTest()
{
SimpleStringMessage test;
test.deserialize(serializer.get(), "{\"testFieldString\":\"qwerty\"}"_ba);
QCOMPARE(test.testFieldString(), "qwerty");
test.deserialize(serializer.get(), "{\"testFieldString\":\"\"}"_ba);
QCOMPARE(test.testFieldString(), "");
test.deserialize(serializer.get(), "{\"testFieldString\":\"null\"}"_ba);
QCOMPARE(test.testFieldString(), "null");
test.deserialize(serializer.get(), "{\"testFieldString\":\"NaN\"}"_ba);
QCOMPARE(test.testFieldString(), "NaN");
test.deserialize(serializer.get(), "{\"testFieldString\":\"Infinity\"}"_ba);
QCOMPARE(test.testFieldString(), "Infinity");
test.deserialize(serializer.get(), "{\"testFieldString\":\"-Infinity\"}"_ba);
QCOMPARE(test.testFieldString(), "-Infinity");
}
void QtProtobufTypesJsonDeserializationTest::ComplexTypeDeserializeTest_data()
{
QTest::addColumn<int>("intField");
QTest::addColumn<QString>("stringField");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("empty_value")
<< 0 << ""
<< "{\"testFieldInt\":0,\"testComplexField\":{\"testFieldString\":\"\"}}"_ba;
QTest::newRow("null_complex_field")
<< 0 << ""
<< "{\"testFieldInt\":0,\"testComplexField\":null}"_ba;
QTest::newRow("value_only_int")
<< 42 << ""
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"\"}}"_ba;
QTest::newRow("value_only_string")
<< 0 << "qwerty"
<< "{\"testFieldInt\":0,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
QTest::newRow("int_and_string")
<< 42 << "qwerty"
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
QTest::newRow("int_and_big_string")
<< 42
<< "YVRfJvjxqbgvFwS1YvOZXgtj5ffGLS7AiNHz9oZIoKbm7z8H79xBuyPkpQXvGoO09OY9xRawx3eOAs9xjo"
"TA1xJhrw28TAcq1CebYlC9WUfQC6hIantaNdyHiKToffi0Zt7la42SRxXZSP4GuxbcZIp53pJnyCwfCy1q"
"dFczT0dmn7h8fpyAdemEavwFeda4d0PApGfSU2jLt39X8kYUBxNM2WgALRBgHdVde87q6Pi5U69TjhMd28"
"W1SFD1DxyogCCrqOct2ZPICoLnrqdF3OdNzjRVLfeyvQ8LgLvRNFR9WfWAyAz79nKgBamd8Ntlvt4Mg35E"
"5gVS2g7AQ7rkm72cBdnW9sCEyGabeXAuH5j4GRbuLT7qBZWDcFLF4SsCdS3WfFGdNHfwaijzykByo71PvF"
"VlTXH2WJWoFvR5FALjBTn7bCdP0pAiSbLCY8Xz2Msc3dBb5Ff9GISPbUpNmUvBdMZMHQvqOmTNXEPpN0b7"
"4MDOMQfWJShOo3NkAvMjs"
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"YVRfJvjxqbgvFwS1Y"
"vOZXgtj5ffGLS7AiNHz9oZIoKbm7z8H79xBuyPkpQXvGoO09OY9xRawx3eOAs9xjoTA1xJhrw28TAcq1Ce"
"bYlC9WUfQC6hIantaNdyHiKToffi0Zt7la42SRxXZSP4GuxbcZIp53pJnyCwfCy1qdFczT0dmn7h8fpyAd"
"emEavwFeda4d0PApGfSU2jLt39X8kYUBxNM2WgALRBgHdVde87q6Pi5U69TjhMd28W1SFD1DxyogCCrqOc"
"t2ZPICoLnrqdF3OdNzjRVLfeyvQ8LgLvRNFR9WfWAyAz79nKgBamd8Ntlvt4Mg35E5gVS2g7AQ7rkm72cB"
"dnW9sCEyGabeXAuH5j4GRbuLT7qBZWDcFLF4SsCdS3WfFGdNHfwaijzykByo71PvFVlTXH2WJWoFvR5FAL"
"jBTn7bCdP0pAiSbLCY8Xz2Msc3dBb5Ff9GISPbUpNmUvBdMZMHQvqOmTNXEPpN0b74MDOMQfWJShOo3NkA"
"vMjs\"}}"_ba;
QTest::newRow("neg_int_and_string")
<< -45 << "qwerty"
<< "{\"testFieldInt\":-45,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::ComplexTypeDeserializeTest()
{
QFETCH(const int, intField);
QFETCH(const QString, stringField);
QFETCH(const QByteArray, serializeData);
SimpleStringMessage stringMessage;
stringMessage.setTestFieldString(stringField);
ComplexMessage test;
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), intField);
QCOMPARE(test.testComplexField(), stringMessage);
}
void QtProtobufTypesJsonDeserializationTest::ResetComplexTypeDeserializeTest_data()
{
QTest::addColumn<int>("intField");
QTest::addColumn<QString>("stringField");
QTest::addColumn<QByteArray>("serializeData");
QTest::newRow("empty_value")
<< 0 << u""_s << "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba;
QTest::newRow("value_only_int")
<< 42 << u""_s << "{\"testFieldInt\":42,\"testComplexField\":{}}"_ba;
QTest::newRow("value_only_string")
<< 0 << u""_s << "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba;
QTest::newRow("int_and_string")
<< 42 << u"qwerty"_s
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
}
void QtProtobufTypesJsonDeserializationTest::ResetComplexTypeDeserializeTest()
{
QFETCH(const int, intField);
QFETCH(const QString, stringField);
QFETCH(const QByteArray, serializeData);
SimpleStringMessage stringMessage;
stringMessage.setTestFieldString(stringField);
ComplexMessage test;
test.setTestFieldInt(intField);
test.setTestComplexField(stringMessage);
// Reset Complex field
test.clearTestComplexField();
test.deserialize(serializer.get(), serializeData);
QCOMPARE(test.testFieldInt(), intField);
QCOMPARE(test.testComplexField(), stringMessage);
}
void QtProtobufTypesJsonDeserializationTest::DefaultConstructedComplexTypeDeserializeTest()
{
ComplexMessage test;
test.deserialize(serializer.get(), "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba);
QCOMPARE(test.testFieldInt(), 0);
QCOMPARE(test.testComplexField().testFieldString(), "");
}
void QtProtobufTypesJsonDeserializationTest::EmptyBytesMessageTest()
{
SimpleBytesMessage test;
test.deserialize(serializer.get(), "{\"testFieldBytes\":\"\"}"_ba);
QCOMPARE(test.testFieldBytes(), "");
}
void QtProtobufTypesJsonDeserializationTest::EmptyStringMessageTest()
{
SimpleStringMessage test;
test.deserialize(serializer.get(), "{\"testFieldString\":\"\"}"_ba);
QCOMPARE(test.testFieldString(), "");
}
QTEST_MAIN(QtProtobufTypesJsonDeserializationTest)
#include "tst_protobuf_deserialization_json_basictypes.moc"

View File

@ -0,0 +1,245 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
//#include "basicmessages.qpb.h"
#include "repeatedmessages.qpb.h"
#include <QObject>
#include <QTest>
#include <QProtobufJsonSerializer>
using namespace Qt::Literals::StringLiterals;
class QtProtobufRepeatedTypesJsonDeserializationTest : public QObject
{
Q_OBJECT
private slots:
void init()
{
serializer.reset(new QProtobufJsonSerializer);
}
void RepeatedStringMessageTest();
void RepeatedFloatMessageTest();
void RepeatedBytesMessageTest();
void RepeatedDoubleMessageTest();
void RepeatedIntMessageTest();
void RepeatedSIntMessageTest();
void RepeatedUIntMessageTest();
void RepeatedInt64MessageTest();
void RepeatedSInt64MessageTest();
void RepeatedUInt64MessageTest();
void RepeatedFixedIntMessageTest();
void RepeatedSFixedIntMessageTest();
void RepeatedFixedInt64MessageTest();
void RepeatedSFixedInt64MessageTest();
void RepeatedComplexMessageTest();
void RepeatedBoolMessageTest();
private:
std::unique_ptr<QProtobufJsonSerializer> serializer;
};
using namespace qtprotobufnamespace::tests;
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedStringMessageTest()
{
RepeatedStringMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedString\":[\"aaaa\",\"bbbbb\",\"ccc\",\"dddddd\",\"eeeee\",\"\"]}"_ba);
QCOMPARE(test.testRepeatedString().count(), 6);
QCOMPARE(test.testRepeatedString(), QStringList({"aaaa","bbbbb","ccc","dddddd","eeeee",""}));
test.deserialize(serializer.get(), "{\"testRepeatedString\":[]"_ba);
QVERIFY(test.testRepeatedString().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedBytesMessageTest()
{
RepeatedBytesMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedBytes\":[\"AQIDBAUG\",\"/////w==\",\"6urq6uo=\",\"AQIDBAUG\"]}"_ba);
QCOMPARE(test.testRepeatedBytes().count(), 4);
QCOMPARE(test.testRepeatedBytes(), QByteArrayList({QByteArray::fromHex("010203040506"),
QByteArray::fromHex("ffffffff"),
QByteArray::fromHex("eaeaeaeaea"),
QByteArray::fromHex("010203040506")}));
//TODO: Serialization for list types works partially incorrect because of appending of values to existing
//Need to make decision if deserialize should reset all protobuf properties or not
RepeatedBytesMessage test2;
test2.deserialize(serializer.get(), "{\"testRepeatedBytes\":[\"AQIDBAUG\",\"\",\"6urq6uo=\",\"AQIDBAUG\"]}"_ba);
QCOMPARE(test2.testRepeatedBytes().count(), 4);
QCOMPARE(test2.testRepeatedBytes(), QByteArrayList({QByteArray::fromHex("010203040506"),
QByteArray::fromHex(""),
QByteArray::fromHex("eaeaeaeaea"),
QByteArray::fromHex("010203040506")}));
test.deserialize(serializer.get(), "{\"testRepeatedBytes\":[]"_ba);
QVERIFY(test.testRepeatedBytes().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedFloatMessageTest()
{
RepeatedFloatMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedFloat\":[0.4,1.2,0.5,3.912348,0.6]}"_ba);
QCOMPARE(test.testRepeatedFloat().count(), 5);
QCOMPARE(test.testRepeatedFloat(), QtProtobuf::floatList({0.4f, 1.2f, 0.5f, 3.912348f, 0.6f}));
test.deserialize(serializer.get(), "{\"testRepeatedFloat\":[]"_ba);
QVERIFY(test.testRepeatedFloat().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedDoubleMessageTest()
{
RepeatedDoubleMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedDouble\":[0.1,0.2,0.3,3.912348239293,0.5]}"_ba);
QCOMPARE(test.testRepeatedDouble().count(), 5);
QCOMPARE(test.testRepeatedDouble(), QtProtobuf::doubleList({0.1,0.2,0.3,3.912348239293,0.5}));
test.deserialize(serializer.get(), "{\"testRepeatedDouble\":[]"_ba);
QVERIFY(test.testRepeatedDouble().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedIntMessageTest()
{
RepeatedIntMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[0,1,321,-65999,123245,-3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 7);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::int32List({0, 1, 321, -65999, 123245, -3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedSIntMessageTest()
{
RepeatedSIntMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,-65999,123245,-3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::sint32List({1, 321, -65999, 123245, -3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedUIntMessageTest()
{
RepeatedUIntMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,0,321,65999,123245,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::uint32List({1, 0, 321, 65999, 123245, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedInt64MessageTest()
{
RepeatedInt64Message test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,-65999,12324523123123,-3,0,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 7);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::int64List({1, 321, -65999, 12324523123123, -3, 0, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedSInt64MessageTest()
{
RepeatedSInt64Message test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,-65999,12324523123123,-3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::sint64List({1, 321, -65999, 12324523123123, -3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedUInt64MessageTest()
{
RepeatedUInt64Message test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,65999,123245,123245324235425234,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::uint64List({1, 321, 65999, 123245, 123245324235425234, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedFixedIntMessageTest()
{
RepeatedFixedIntMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,65999,12324523,3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::fixed32List({1, 321, 65999, 12324523, 3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedSFixedIntMessageTest()
{
RepeatedSFixedIntMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[0,1,321,-65999,12324523,-3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 7);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::sfixed32List({0, 1, 321, -65999, 12324523, -3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedFixedInt64MessageTest()
{
RepeatedFixedInt64Message test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,65999,123245324235425234,3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::fixed64List({1, 321, 65999, 123245324235425234, 3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedSFixedInt64MessageTest()
{
RepeatedSFixedInt64Message test;
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[1,321,-65999,123245324235425234,-3,3]}"_ba);
QCOMPARE(test.testRepeatedInt().count(), 6);
QCOMPARE(test.testRepeatedInt(), QtProtobuf::sfixed64List({1, 321, -65999, 123245324235425234, -3, 3}));
test.deserialize(serializer.get(), "{\"testRepeatedInt\":[]"_ba);
QVERIFY(test.testRepeatedInt().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedComplexMessageTest()
{
RepeatedComplexMessage test;
test.deserialize(serializer.get(), "{\"testRepeatedComplex\":[{\"testFieldInt\":21,\"testComplexField\":"
"{\"testFieldString\":\"12345\"}},{\"testFieldInt\":22,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}},{\"testFieldInt\":23,\"testComplexField\":"
"{\"testFieldString\":\"\"}}]}"_ba);
QCOMPARE(test.testRepeatedComplex().count(), 3);
for (auto element: test.testRepeatedComplex()) {
qWarning() << "testFieldInt = " << element.testFieldInt()
<< "testFieldString = " << element.testComplexField().testFieldString();
}
QCOMPARE(test.testRepeatedComplex().at(0).testFieldInt(), 21);
QCOMPARE(test.testRepeatedComplex().at(0).testComplexField().testFieldString(), QString("12345"));
QCOMPARE(test.testRepeatedComplex().at(1).testFieldInt(), 22);
QCOMPARE(test.testRepeatedComplex().at(1).testComplexField().testFieldString(), QString("qwerty"));
QCOMPARE(test.testRepeatedComplex().at(2).testFieldInt(), 23);
QCOMPARE(test.testRepeatedComplex().at(2).testComplexField().testFieldString(), QString(""));
test.deserialize(serializer.get(), "{\"testRepeatedComplex\":[]}"_ba);
QVERIFY(!test.testRepeatedComplex().isEmpty());
}
void QtProtobufRepeatedTypesJsonDeserializationTest::RepeatedBoolMessageTest()
{
RepeatedBoolMessage boolMsg;
boolMsg.deserialize(serializer.get(), "{\"testRepeatedBool\":[true,true,true,false,false,false,false,false,false,false,false,false,true]}"_ba);
QCOMPARE(serializer->deserializationError(), QAbstractProtobufSerializer::NoError);
QtProtobuf::boolList expected({ true, true, true, false, false, false, false,
false, false, false, false, false, true });
QCOMPARE(boolMsg.testRepeatedBool().count(), 13);
QCOMPARE(boolMsg.testRepeatedBool(), expected);
}
QTEST_MAIN(QtProtobufRepeatedTypesJsonDeserializationTest)
#include "tst_protobuf_deserialization_json_repeatedtypes.moc"

View File

@ -0,0 +1,603 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "basicmessages.qpb.h"
#include <QProtobufJsonSerializer>
#include <QTest>
#include <QJsonDocument>
using namespace Qt::Literals::StringLiterals;
class QtProtobufTypesJsonSerializationTest : public QObject
{
Q_OBJECT
private slots:
void init() { qRegisterProtobufTypes(); m_serializer.reset(new QProtobufJsonSerializer); }
void BoolMessageSerializeTest_data();
void BoolMessageSerializeTest();
void IntMessageSerializeTest_data();
void IntMessageSerializeTest();
void UIntMessageSerializeTest_data();
void UIntMessageSerializeTest();
void SIntMessageSerializeTest_data();
void SIntMessageSerializeTest();
void Int64MessageSerializeTest_data();
void Int64MessageSerializeTest();
void UInt64MessageSerializeTest_data();
void UInt64MessageSerializeTest();
void SInt64MessageSerializeTest_data();
void SInt64MessageSerializeTest();
void FixedInt32MessageSerializeTest_data();
void FixedInt32MessageSerializeTest();
void FixedInt64MessageSerializeTest_data();
void FixedInt64MessageSerializeTest();
void SFixedInt32MessageSerializeTest_data();
void SFixedInt32MessageSerializeTest();
void SFixedInt64MessageSerializeTest_data();
void SFixedInt64MessageSerializeTest();
void FloatMessageSerializeTest_data();
void FloatMessageSerializeTest();
void DoubleMessageSerializeTest_data();
void DoubleMessageSerializeTest();
void StringMessageSerializeTest();
void ComplexTypeSerializeTest_data();
void ComplexTypeSerializeTest();
void ResetComplexTypeSerializeTest_data();
void ResetComplexTypeSerializeTest();
void DefaultConstructedComplexTypeSerializeTest();
void EmptyBytesMessageTest();
void EmptyStringMessageTest();
/* TBD: Add ANY type support for Json Serializer
void OneofMessageEmptyTest();
void OneofMessageClearTest();
void OneofMessageIntTest();
void OneofMessageComplexTest();
*/
private:
std::unique_ptr<QProtobufJsonSerializer> m_serializer;
};
using namespace qtprotobufnamespace::tests;
void QtProtobufTypesJsonSerializationTest::BoolMessageSerializeTest_data()
{
QTest::addColumn<bool>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("True") << true << qsizetype(22) << "{\"testFieldBool\":true}"_ba;
QTest::newRow("False") << false << qsizetype(23) << "{\"testFieldBool\":false}"_ba;
}
void QtProtobufTypesJsonSerializationTest::BoolMessageSerializeTest()
{
QFETCH(const bool, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleBoolMessage test;
test.setTestFieldBool(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::IntMessageSerializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("555") << 555 << qsizetype(20) << "{\"testFieldInt\":555}"_ba;
QTest::newRow("0") << 0 << qsizetype(18) << "{\"testFieldInt\":0}"_ba;
}
void QtProtobufTypesJsonSerializationTest::IntMessageSerializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleIntMessage test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::UIntMessageSerializeTest_data()
{
QTest::addColumn<uint32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint32_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint32_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
}
void QtProtobufTypesJsonSerializationTest::UIntMessageSerializeTest()
{
QFETCH(const uint32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleUIntMessage test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::SIntMessageSerializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int32_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int32_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int32_t)-1 << qsizetype(19) << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << qsizetype(21) << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int32_t)-63585 << qsizetype(23) << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SIntMessageSerializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSIntMessage test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::Int64MessageSerializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int64_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int64_t)-1 << qsizetype(19) << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << qsizetype(21) << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << qsizetype(23) << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::Int64MessageSerializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleInt64Message test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::UInt64MessageSerializeTest_data()
{
QTest::addColumn<uint64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint64_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (uint64_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (uint64_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
}
void QtProtobufTypesJsonSerializationTest::UInt64MessageSerializeTest()
{
QFETCH(const QtProtobuf::uint64, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleUInt64Message test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::SInt64MessageSerializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int64_t)15 << qsizetype(19) << "{\"testFieldInt\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << qsizetype(20) << "{\"testFieldInt\":300}"_ba;
QTest::newRow("65545") << (int64_t)65545 << qsizetype(22) << "{\"testFieldInt\":65545}"_ba;
QTest::newRow("-1") << (int64_t)-1 << qsizetype(19) << "{\"testFieldInt\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << qsizetype(21) << "{\"testFieldInt\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << qsizetype(23) << "{\"testFieldInt\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SInt64MessageSerializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSInt64Message test;
test.setTestFieldInt(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::FixedInt32MessageSerializeTest_data()
{
QTest::addColumn<uint32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint32_t)15 << qsizetype(26) << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (uint32_t)300 << qsizetype(27) << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545")
<< (uint32_t)65545 << qsizetype(29) << "{\"testFieldFixedInt32\":65545}"_ba;
}
void QtProtobufTypesJsonSerializationTest::FixedInt32MessageSerializeTest()
{
QFETCH(const uint32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleFixedInt32Message test;
test.setTestFieldFixedInt32(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::FixedInt64MessageSerializeTest_data()
{
QTest::addColumn<uint64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (uint64_t)15 << qsizetype(26) << "{\"testFieldFixedInt64\":15}"_ba;
QTest::newRow("300") << (uint64_t)300 << qsizetype(27) << "{\"testFieldFixedInt64\":300}"_ba;
QTest::newRow("65545")
<< (uint64_t)65545 << qsizetype(29) << "{\"testFieldFixedInt64\":65545}"_ba;
}
void QtProtobufTypesJsonSerializationTest::FixedInt64MessageSerializeTest()
{
QFETCH(const uint64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleFixedInt64Message test;
test.setTestFieldFixedInt64(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::SFixedInt32MessageSerializeTest_data()
{
QTest::addColumn<int32_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int32_t)15 << qsizetype(26) << "{\"testFieldFixedInt32\":15}"_ba;
QTest::newRow("300") << (int32_t)300 << qsizetype(27) << "{\"testFieldFixedInt32\":300}"_ba;
QTest::newRow("65545")
<< (int32_t)65545 << qsizetype(29) << "{\"testFieldFixedInt32\":65545}"_ba;
QTest::newRow("-1") << (int32_t)-1 << qsizetype(26) << "{\"testFieldFixedInt32\":-1}"_ba;
QTest::newRow("-462") << (int32_t)-462 << qsizetype(28) << "{\"testFieldFixedInt32\":-462}"_ba;
QTest::newRow("-63585")
<< (int32_t)-63585 << qsizetype(30) << "{\"testFieldFixedInt32\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SFixedInt32MessageSerializeTest()
{
QFETCH(const int32_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSFixedInt32Message test;
test.setTestFieldFixedInt32(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::SFixedInt64MessageSerializeTest_data()
{
QTest::addColumn<int64_t>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("15") << (int64_t)15 << qsizetype(26) << "{\"testFieldFixedInt64\":15}"_ba;
QTest::newRow("300") << (int64_t)300 << qsizetype(27) << "{\"testFieldFixedInt64\":300}"_ba;
QTest::newRow("65545")
<< (int64_t)65545 << qsizetype(29) << "{\"testFieldFixedInt64\":65545}"_ba;
QTest::newRow("-1") << (int64_t)-1 << qsizetype(26) << "{\"testFieldFixedInt64\":-1}"_ba;
QTest::newRow("-462") << (int64_t)-462 << qsizetype(28) << "{\"testFieldFixedInt64\":-462}"_ba;
QTest::newRow("-63585") << (int64_t)-63585 << qsizetype(30)
<< "{\"testFieldFixedInt64\":-63585}"_ba;
}
void QtProtobufTypesJsonSerializationTest::SFixedInt64MessageSerializeTest()
{
QFETCH(const int64_t, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleSFixedInt64Message test;
test.setTestFieldFixedInt64(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::FloatMessageSerializeTest_data()
{
QTest::addColumn<float>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("float_value_0_1") << 0.1f << qsizetype(22) << "{\"testFieldFloat\":0.1}"_ba;
QTest::newRow("float_value_min") << std::numeric_limits<float>::min() << qsizetype(31)
<< "{\"testFieldFloat\":1.175494e-38}"_ba;
QTest::newRow("float_value_max") << std::numeric_limits<float>::max() << qsizetype(31)
<< "{\"testFieldFloat\":3.402823e+38}"_ba;
QTest::newRow("float_neg_value_4_2")
<< -4.2f << qsizetype(23) << "{\"testFieldFloat\":-4.2}"_ba;
QTest::newRow("float_neg_value_0_0")
<< (float)-0.0f << qsizetype(20) << "{\"testFieldFloat\":0}"_ba;
}
void QtProtobufTypesJsonSerializationTest::FloatMessageSerializeTest()
{
QFETCH(const float, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleFloatMessage test;
test.setTestFieldFloat(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::DoubleMessageSerializeTest_data()
{
QTest::addColumn<double>("value");
QTest::addColumn<qsizetype>("expectedSize");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("double_value_0_1") << 0.1 << qsizetype(23)
<< "{\"testFieldDouble\":0.1}"_ba;
QTest::newRow("double_value_min")
<< std::numeric_limits<double>::min() << qsizetype(40)
<< "{\"testFieldDouble\":2.2250738585072e-308}"_ba;
QTest::newRow("double_value_max")
<< std::numeric_limits<double>::max() << qsizetype(40)
<< "{\"testFieldDouble\":1.7976931348623e+308}"_ba;
QTest::newRow("double_neg_value_4_2") << -4.2 << qsizetype(24)
<< "{\"testFieldDouble\":-4.2}"_ba;
QTest::newRow("double_value_0_0") << 0.0 << qsizetype(21)
<< "{\"testFieldDouble\":0}"_ba;
}
void QtProtobufTypesJsonSerializationTest::DoubleMessageSerializeTest()
{
QFETCH(const double, value);
QFETCH(const qsizetype, expectedSize);
QFETCH(const QByteArray, expectedData);
SimpleDoubleMessage test;
test.setTestFieldDouble(value);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result.size(), expectedSize);
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::StringMessageSerializeTest()
{
SimpleStringMessage test;
test.setTestFieldString("qwerty");
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"qwerty\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestFieldString("");
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestFieldString("null");
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"null\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestFieldString("NaN");
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"NaN\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestFieldString("Infinity");
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"Infinity\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestFieldString("-Infinity");
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"-Infinity\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::ComplexTypeSerializeTest_data()
{
QTest::addColumn<int>("intField");
QTest::addColumn<QString>("stringField");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("empty_value")
<< 0 << ""
<< "{\"testFieldInt\":0,\"testComplexField\":{\"testFieldString\":\"\"}}"_ba;
QTest::newRow("value_only_int")
<< 42 << ""
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"\"}}"_ba;
QTest::newRow("value_only_string")
<< 0 << "qwerty"
<< "{\"testFieldInt\":0,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
QTest::newRow("int_and_string")
<< 42 << "qwerty"
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
QTest::newRow("int_and_big_string")
<< 42
<< "YVRfJvjxqbgvFwS1YvOZXgtj5ffGLS7AiNHz9oZIoKbm7z8H79xBuyPkpQXvGoO09OY9xRawx3eOAs9xjo"
"TA1xJhrw28TAcq1CebYlC9WUfQC6hIantaNdyHiKToffi0Zt7la42SRxXZSP4GuxbcZIp53pJnyCwfCy1q"
"dFczT0dmn7h8fpyAdemEavwFeda4d0PApGfSU2jLt39X8kYUBxNM2WgALRBgHdVde87q6Pi5U69TjhMd28"
"W1SFD1DxyogCCrqOct2ZPICoLnrqdF3OdNzjRVLfeyvQ8LgLvRNFR9WfWAyAz79nKgBamd8Ntlvt4Mg35E"
"5gVS2g7AQ7rkm72cBdnW9sCEyGabeXAuH5j4GRbuLT7qBZWDcFLF4SsCdS3WfFGdNHfwaijzykByo71PvF"
"VlTXH2WJWoFvR5FALjBTn7bCdP0pAiSbLCY8Xz2Msc3dBb5Ff9GISPbUpNmUvBdMZMHQvqOmTNXEPpN0b7"
"4MDOMQfWJShOo3NkAvMjs"
<< "{\"testFieldInt\":42,\"testComplexField\":{\"testFieldString\":\"YVRfJvjxqbgvFwS1Y"
"vOZXgtj5ffGLS7AiNHz9oZIoKbm7z8H79xBuyPkpQXvGoO09OY9xRawx3eOAs9xjoTA1xJhrw28TAcq1Ce"
"bYlC9WUfQC6hIantaNdyHiKToffi0Zt7la42SRxXZSP4GuxbcZIp53pJnyCwfCy1qdFczT0dmn7h8fpyAd"
"emEavwFeda4d0PApGfSU2jLt39X8kYUBxNM2WgALRBgHdVde87q6Pi5U69TjhMd28W1SFD1DxyogCCrqOc"
"t2ZPICoLnrqdF3OdNzjRVLfeyvQ8LgLvRNFR9WfWAyAz79nKgBamd8Ntlvt4Mg35E5gVS2g7AQ7rkm72cB"
"dnW9sCEyGabeXAuH5j4GRbuLT7qBZWDcFLF4SsCdS3WfFGdNHfwaijzykByo71PvFVlTXH2WJWoFvR5FAL"
"jBTn7bCdP0pAiSbLCY8Xz2Msc3dBb5Ff9GISPbUpNmUvBdMZMHQvqOmTNXEPpN0b74MDOMQfWJShOo3NkA"
"vMjs\"}}"_ba;
QTest::newRow("neg_int_and_string")
<< -45 << "qwerty"
<< "{\"testFieldInt\":-45,\"testComplexField\":{\"testFieldString\":\"qwerty\"}}"_ba;
}
void QtProtobufTypesJsonSerializationTest::ComplexTypeSerializeTest()
{
QFETCH(const int, intField);
QFETCH(const QString, stringField);
QFETCH(const QByteArray, expectedData);
SimpleStringMessage stringMessage;
stringMessage.setTestFieldString(stringField);
ComplexMessage test, testStd;
test.setTestFieldInt(intField);
test.setTestComplexField(stringMessage);
testStd.setTestFieldInt(intField);
testStd.setTestComplexField(stringMessage);
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::ResetComplexTypeSerializeTest_data()
{
QTest::addColumn<int>("intField");
QTest::addColumn<QString>("stringField");
QTest::addColumn<QByteArray>("expectedData");
QTest::newRow("empty_value")
<< 0 << u""_s << "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba;
QTest::newRow("value_only_int")
<< 42 << u""_s << "{\"testFieldInt\":42,\"testComplexField\":{}}"_ba;
QTest::newRow("value_only_string")
<< 0 << u"qwerty"_s << "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba;
QTest::newRow("int_and_string")
<< 42 << u"qwerty"_s << "{\"testFieldInt\":42,\"testComplexField\":{}}"_ba;
}
void QtProtobufTypesJsonSerializationTest::ResetComplexTypeSerializeTest()
{
QFETCH(const int, intField);
QFETCH(const QString, stringField);
QFETCH(const QByteArray, expectedData);
SimpleStringMessage stringMessage;
stringMessage.setTestFieldString(stringField);
ComplexMessage test;
test.setTestFieldInt(intField);
test.setTestComplexField(stringMessage);
// Reset Complex field
test.clearTestComplexField();
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, expectedData);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::DefaultConstructedComplexTypeSerializeTest()
{
ComplexMessage test;
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldInt\":0,\"testComplexField\":{}}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::EmptyBytesMessageTest()
{
SimpleBytesMessage msg;
QByteArray result = msg.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldBytes\":\"\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufTypesJsonSerializationTest::EmptyStringMessageTest()
{
SimpleStringMessage msg;
QByteArray result = msg.serialize(m_serializer.get());
QCOMPARE(result, "{\"testFieldString\":\"\"}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
/* TBD: Add ANY type support for Json Serializer
void QtProtobufTypesJsonSerializationTest::OneofMessageEmptyTest()
{
}
void QtProtobufTypesJsonSerializationTest::OneofMessageIntTest()
{
}
void QtProtobufTypesJsonSerializationTest::OneofMessageClearTest()
{
}
void QtProtobufTypesJsonSerializationTest::OneofMessageComplexTest()
{
}
*/
QTEST_MAIN(QtProtobufTypesJsonSerializationTest)
#include "tst_protobuf_serialization_json_basictypes.moc"

View File

@ -0,0 +1,123 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "mapmessages.qpb.h"
#include <QObject>
#include <QProtobufJsonSerializer>
#include <QTest>
using namespace qtprotobufnamespace::tests;
using namespace Qt::Literals::StringLiterals;
class QtProtobufJsonMapTypesSerializationTest : public QObject
{
Q_OBJECT
private slots:
void init() { m_serializer.reset(new QProtobufJsonSerializer); }
void SimpleFixed32StringMapSerializeTest();
void SimpleSFixed32StringMapSerializeTest();
void SimpleInt32StringMapSerializeTest();
void SimpleSInt32StringMapSerializeTest();
void SimpleUInt32StringMapSerializeTest();
void SimpleFixed64StringMapSerializeTest();
void SimpleSFixed64StringMapSerializeTest();
void SimpleInt64StringMapSerializeTest();
void SimpleSInt64StringMapSerializeTest();
void SimpleUInt64StringMapSerializeTest();
void SimpleStringStringMapSerializeTest();
private:
std::unique_ptr<QProtobufJsonSerializer> m_serializer;
};
void QtProtobufJsonMapTypesSerializationTest::SimpleFixed32StringMapSerializeTest()
{
SimpleFixed32StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { 42, { "fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleSFixed32StringMapSerializeTest()
{
SimpleSFixed32StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { -42, { "minus fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleInt32StringMapSerializeTest()
{
SimpleInt32StringMapMessage test;
test.setMapField({ { -10, { "minus ten" } }, { 42, { "fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleSInt32StringMapSerializeTest()
{
SimpleSInt32StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { -42, { "minus fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleUInt32StringMapSerializeTest()
{
SimpleUInt32StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { 42, { "fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleFixed64StringMapSerializeTest()
{
SimpleFixed64StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { 42, { "fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleSFixed64StringMapSerializeTest()
{
SimpleSFixed64StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { -42, { "minus fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleInt64StringMapSerializeTest()
{
SimpleInt64StringMapMessage test;
test.setMapField({ { -10, { "minus ten" } }, { 42, { "fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleSInt64StringMapSerializeTest()
{
SimpleSInt64StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { -42, { "minus fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleUInt64StringMapSerializeTest()
{
SimpleUInt64StringMapMessage test;
test.setMapField({ { 10, { "ten" } }, { 42, { "fourty two" } }, { 15, { "fifteen" } } });
QByteArray result = test.serialize(m_serializer.get());
}
void QtProtobufJsonMapTypesSerializationTest::SimpleStringStringMapSerializeTest()
{
SimpleStringStringMapMessage test;
test.setMapField({ { "ben", "ten" },
{ "what is the answer?", "fourty two" },
{ "sweet", "fifteen" } });
QByteArray result = test.serialize(m_serializer.get());
}
QTEST_MAIN(QtProtobufJsonMapTypesSerializationTest)
#include "tst_protobuf_serialization_json_maptypes.moc"

View File

@ -0,0 +1,293 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
//#include "basicmessages.qpb.h"
#include "repeatedmessages.qpb.h"
#include <QProtobufJsonSerializer>
#include <QJsonDocument>
#include <QTest>
using namespace Qt::Literals::StringLiterals;
class QtProtobufRepeatedTypesJsonSerializationTest : public QObject
{
Q_OBJECT
private slots:
void init() {
m_serializer.reset(new QProtobufJsonSerializer);
}
void RepeatedIntMessageTest();
void RepeatedSIntMessageTest();
void RepeatedUIntMessageTest();
void RepeatedInt64MessageTest();
void RepeatedSInt64MessageTest();
void RepeatedUInt64MessageTest();
void RepeatedFixedIntMessageTest();
void RepeatedSFixedIntMessageTest();
void RepeatedFixedInt64MessageTest();
void RepeatedSFixedInt64MessageTest();
void RepeatedStringMessageTest();
void RepeatedFloatMessageTest();
void RepeatedDoubleMessageTest();
void RepeatedBytesMessageTest();
void RepeatedComplexMessageTest();
void RepeatedBoolMessageTest();
private:
std::unique_ptr<QProtobufJsonSerializer> m_serializer;
};
using namespace qtprotobufnamespace::tests;
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedIntMessageTest()
{
RepeatedIntMessage test;
test.setTestRepeatedInt({0, 1, 321, -65999, 123245, -3, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[0,1,321,-65999,123245,-3,3]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::int32List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedSIntMessageTest()
{
RepeatedSIntMessage test;
test.setTestRepeatedInt({1, 321, -65999, 123245, -3, 3, 0});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,123245,-3,3,0]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::sint32List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedUIntMessageTest()
{
RepeatedUIntMessage test;
test.setTestRepeatedInt({1, 0, 321, 65999, 123245, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,0,321,65999,123245,3]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::uint32List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedInt64MessageTest()
{
RepeatedInt64Message test;
test.setTestRepeatedInt({1, 321, -65999, 12324523123123, -3, 0, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,12324523123123,-3,0,3]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::int64List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedSInt64MessageTest()
{
RepeatedSInt64Message test;
test.setTestRepeatedInt({1, 321, -65999, 12324523123123, 0, -3, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,12324523123123,0,-3,3]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::sint64List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedUInt64MessageTest()
{
RepeatedUInt64Message test;
test.setTestRepeatedInt({1, 321, 0, 65999, 123245, 123245324235425234, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,0,65999,123245,123245324235425234,3]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::uint64List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedFixedIntMessageTest()
{
RepeatedFixedIntMessage test;
test.setTestRepeatedInt({1, 321, 65999, 12324523, 3, 3, 0});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,65999,12324523,3,3,0]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::fixed32List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedSFixedIntMessageTest()
{
RepeatedSFixedIntMessage test;
test.setTestRepeatedInt({0, 1, 321, -65999, 12324523, -3, 3});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[0,1,321,-65999,12324523,-3,3]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::sfixed32List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedFixedInt64MessageTest()
{
RepeatedFixedInt64Message test;
test.setTestRepeatedInt({1, 321, 65999, 123245324235425234, 3, 3, 0});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,65999,123245324235425234,3,3,0]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::fixed64List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedSFixedInt64MessageTest()
{
RepeatedSFixedInt64Message test;
test.setTestRepeatedInt({1, 321, -65999, 123245324235425234, -3, 3, 0});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[1,321,-65999,123245324235425234,-3,3,0]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedInt(QtProtobuf::sfixed64List());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedInt\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedStringMessageTest()
{
RepeatedStringMessage test;
test.setTestRepeatedString({"aaaa","bbbbb","ccc","dddddd","eeeee", ""});
QByteArray result = test.serialize(m_serializer.get());
QCOMPARE(result,
"{\"testRepeatedString\":[\"aaaa\",\"bbbbb\",\"ccc\",\"dddddd\",\"eeeee\",\"\"]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
test.setTestRepeatedString(QStringList());
result = test.serialize(m_serializer.get());
QCOMPARE(result, "{\"testRepeatedString\":[]}"_ba);
QVERIFY(!QJsonDocument::fromJson(result).isNull());
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedFloatMessageTest()
{
RepeatedFloatMessage test;
test.setTestRepeatedFloat({0.4f, 1.2f, 0.5f, 3.912348f, 0.6f});
QByteArray result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedFloat\":[0.4,1.2,0.5,3.912348,0.6]}"_ba);
test.setTestRepeatedFloat(QtProtobuf::floatList());
result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedFloat\":[]}"_ba);
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedDoubleMessageTest()
{
RepeatedDoubleMessage test;
test.setTestRepeatedDouble({0.1, 0.2, 0.3, 3.912348239293, 0.5});
QByteArray result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedDouble\":[0.1,0.2,0.3,3.912348239293,0.5]}"_ba);
test.setTestRepeatedDouble(QtProtobuf::doubleList());
result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedDouble\":[]}"_ba);
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedBytesMessageTest()
{
RepeatedBytesMessage test;
test.setTestRepeatedBytes({QByteArray::fromHex("010203040506"),
QByteArray::fromHex("ffffffff"),
QByteArray::fromHex("eaeaeaeaea"),
QByteArray::fromHex("010203040506")});
QByteArray result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result,
"{\"testRepeatedBytes\":[\"AQIDBAUG\",\"/////w==\",\"6urq6uo=\",\"AQIDBAUG\"]}"_ba);
test.setTestRepeatedBytes(QByteArrayList());
result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedBytes\":[]}"_ba);
test.setTestRepeatedBytes({QByteArray::fromHex("010203040506"),
QByteArray::fromHex(""),
QByteArray::fromHex("eaeaeaeaea"),
QByteArray::fromHex("010203040506")});
result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result,
"{\"testRepeatedBytes\":[\"AQIDBAUG\",\"\",\"6urq6uo=\",\"AQIDBAUG\"]}"_ba);
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedComplexMessageTest()
{
SimpleStringMessage stringMsg;
stringMsg.setTestFieldString("qwerty");
ComplexMessage msg;
msg.setTestFieldInt(25);
msg.setTestComplexField(stringMsg);
RepeatedComplexMessage test;
test.setTestRepeatedComplex({msg, msg, msg});
QByteArray result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result,
"{\"testRepeatedComplex\":[{\"testFieldInt\":25,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}},{\"testFieldInt\":25,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}},{\"testFieldInt\":25,\"testComplexField\":"
"{\"testFieldString\":\"qwerty\"}}]}"_ba);
test.setTestRepeatedComplex({});
result = test.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedComplex\":[]}"_ba);
}
void QtProtobufRepeatedTypesJsonSerializationTest::RepeatedBoolMessageTest()
{
RepeatedBoolMessage boolMsg;
boolMsg.setTestRepeatedBool({ true, true, true, false, false, false, false, false,
false, false, false, false, true });
QByteArray result = boolMsg.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedBool\":[true,true,true,false,false,false,false,"
"false,false,false,false,false,true]}"_ba);
boolMsg.setTestRepeatedBool(QtProtobuf::boolList());
result = boolMsg.serialize(m_serializer.get());
QVERIFY(!QJsonDocument::fromJson(result).isNull());
QCOMPARE(result, "{\"testRepeatedBool\":[]}"_ba);
}
QTEST_MAIN(QtProtobufRepeatedTypesJsonSerializationTest)
#include "tst_protobuf_serialization_json_repeatedtypes.moc"