Skip to content

Custom field codec support #21

Description

@xor-gate

Hi @smurfomen,

Currently i'm working on the internal company application which already uses the QSerializer I modified and upstreamed.
I have a proposal/implementation for custom value serializer/deserializer without the underlaying implementation of QVariant but direct accessing the toJson and fromJson (generated) methods.

Why do we need this?
So good question, let think of a use case where we want to have a native QDateTime in a class as serializable property but we want to extend it with our custom wrapper class. For example the JSON string presentation uses format ISODateWithMs. To put the encode/decode directly in the custom serializers the application logic can deal with Qt native types and don't have need to have helper functions in the application.

As an example:

class CustomDateTime : public QSerializerValue, public QDateTime {
public:
    using QDateTime::QDateTime;

    // Assignment Operator
    CustomDateTime& operator=(const QDateTime& other) {
        // Guard against self-assignment
        if (this != &other) {
            // Explicitly call the base class assignment operator
            QDateTime::operator=(other);
        }

        // Return *this to allow chained assignments (a = b = c)
        return *this;
    }

    QJsonValue toJson(void) const {
        return QJsonValue(static_cast<const QDateTime&>(*this).toString(Qt::ISODateWithMs));
    }

    void fromJson(const QJsonValue & varname) {
        if (!varname.isString()) {
            return;
        }
        static_cast<QDateTime &>(*this) = QDateTime::fromString(varname.toString(), Qt::ISODateWithMs);
    }
};

I introduced the new QSerializerValue which is an abstract class with virtual function for the toJson/fromJson. It doesn't do anything but makes it clear which functions need to be implemented. I also going to add the XML support. But for my case JSON is enough.

I will introduce QS_VALUE to embedded a property where the type needs to inherit from QSerializerValue. It is directly compatible with QS_FIELD for already serializable types. So with this a class doesn't need to handle QVariant types.

#ifdef QS_HAS_JSON
#define QS_JSON_VALUE(type, name) \
public: \
    Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json, name))                  \
    private:                                                                                \
    QJsonValue GET(json, name)() const {                                                    \
        auto val = name.toJson();                                                    \
        return val;                                                             \
}                                                                                       \
    void SET(json, name)(const QJsonValue & varname) {                                      \
        name.fromJson(varname);                                                             \
    }
#else
#define QS_JSON_VALUE(type, name)
#endif

#define QS_BIND_VALUE(type, name) \
    QS_JSON_VALUE(type, name)

#define QS_VALUE(type, name) \
    QS_DECLARE_MEMBER(type, name)                                                           \
    QS_BIND_VALUE(type, name)

The QS_FIELD is implement for JSON as follows:

#ifdef QS_HAS_JSON
#define QS_JSON_FIELD(type, name)                                                           \
    Q_PROPERTY(QJsonValue name READ GET(json, name) WRITE SET(json, name))                  \
    private:                                                                                \
        QJsonValue GET(json, name)() const {                                                \
            QJsonValue val = QJsonValue::fromVariant(QVariant(name));                       \

I have a prototype branch here: https://github.com/xor-gate/QSerializer/tree/feature/custom-value-codec

I need to work in this in the upcomming time for our internal project, hope I can clean it up to get it in the upstream library.

Thanks in advance!

  • Jerry

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions