Qt模仿nlohmann::json进行序列化和反序列化

代码实现部分

cpp 复制代码
#pragma once

#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonValue>
#include <QString>
#include <QVector>
#include <QList>
#include <array>
#include <type_traits>

// ============ 类型转换辅助 ============
// 基础类型 -> QJsonValue
namespace QJsonConvert
{
    // 基础类型
    inline QJsonValue toJson(int v)             { return v; }
    inline QJsonValue toJson(double v)          { return v; }
    inline QJsonValue toJson(float v)           { return static_cast<double>(v); }
    inline QJsonValue toJson(bool v)            { return v; }
    inline QJsonValue toJson(const QString& v)  { return v; }
    inline QJsonValue toJson(qint64 v)          { return v; }
    inline QJsonValue toJson(const char* v)     { return QString(v); }
    inline QJsonValue toJson(const std::string& v) { return QString::fromStdString(v); }

    inline void fromJson(const QJsonValue& j, int& v)      { v = j.toInt(v); }
    inline void fromJson(const QJsonValue& j, double& v)   { v = j.toDouble(v); }
    inline void fromJson(const QJsonValue& j, float& v)    { v = static_cast<float>(j.toDouble(v)); }
    inline void fromJson(const QJsonValue& j, bool& v)     { v = j.toBool(v); }
    inline void fromJson(const QJsonValue& j, QString& v)  { v = j.toString(v); }
    inline void fromJson(const QJsonValue& j, qint64& v)   { v = static_cast<qint64>(j.toDouble(v)); }
    inline void fromJson(const QJsonValue& j, std::string& v) { v = j.toString(QString::fromStdString(v)).toStdString(); }

    // 自定义类型:通过成员函数 toJson()/fromJson() 自动调用
    template <typename T>
    auto toJson(const T& v) -> decltype(v.toJson(), QJsonValue{})
    {
        return v.toJson();
    }

    template <typename T>
    auto fromJson(const QJsonValue& j, T& v) -> decltype(v.fromJson(QJsonObject{}), void())
    {
        v.fromJson(j.toObject());
    }

    //std::array
    template <typename T, std::size_t N>
    QJsonValue toJson(const std::array<T,N>& vec)
    {
        QJsonArray arr;
        for (const auto& item : vec) arr.append(toJson(item));
        return arr;
    }

    template <typename T, std::size_t N>
    void fromJson(const QJsonValue& j, std::array<T,N>& vec)
    {
        const QJsonArray arr = j.toArray();
        const int count = std::min<int>(N, arr.size());
        for (int i=0; i<count; ++i)
        {
            const auto& v = arr.at(i);
            fromJson(v, vec[i]);
        }
        for (std::size_t i = count; i < N; ++i)
        {
            vec[i] = T{};
        }
    }

    // QVector
    template <typename T>
    QJsonValue toJson(const QVector<T>& vec)
    {
        QJsonArray arr;
        for (const auto& item : vec) arr.append(toJson(item));
        return arr;
    }

    template <typename T>
    void fromJson(const QJsonValue& j, QVector<T>& vec)
    {
        vec.clear();
        const QJsonArray arr = j.toArray();
        vec.reserve(arr.size());
        for (const auto& v : arr) {
            T item{};
            fromJson(v, item);
            vec.append(item);
        }
    }

    //QList
    template <typename T>
    QJsonValue toJson(const QList<T>& vec)
    {
        QJsonArray arr;
        for (const auto& item : vec) arr.append(toJson(item));
        return arr;
    }

    template <typename T>
    void fromJson(const QJsonValue& j, QList<T>& vec)
    {
        vec.clear();
        const QJsonArray arr = j.toArray();
        for (const auto& v : arr) {
            T item{};
            fromJson(v, item);
            vec.append(item);
        }
    }
} // namespace QJsonConvert


#define QJ_CONCAT_INNER(a, b) a ## b
#define QJ_CONCAT(a, b) QJ_CONCAT_INNER(a, b)

// ============ 可变参数宏展开工具 ============
// 计算参数个数 (最多支持 100 个,可继续扩展)
#define QJ_EXPAND(x) x
#define QJ_GET_NTH_ARG( \
    _1,_2,_3,_4,_5,_6,_7,_8,_9,_10, \
    _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
    _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
    _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
    _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
    _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
    _61,_62,_63,_64,_65,_66,_67,_68,_69,_70, \
    _71,_72,_73,_74,_75,_76,_77,_78,_79,_80, \
    _81,_82,_83,_84,_85,_86,_87,_88,_89,_90, \
    _91,_92,_93,_94,_95,_96,_97,_98,_99,_100, \
    N, ...) N

#define QJ_COUNT(...) QJ_EXPAND(QJ_GET_NTH_ARG(__VA_ARGS__, \
    100,99,98,97,96,95,94,93,92,91, \
    90,89,88,87,86,85,84,83,82,81, \
    80,79,78,77,76,75,74,73,72,71, \
    70,69,68,67,66,65,64,63,62,61, \
    60,59,58,57,56,55,54,53,52,51, \
    50,49,48,47,46,45,44,43,42,41, \
    40,39,38,37,36,35,34,33,32,31, \
    30,29,28,27,26,25,24,23,22,21, \
    20,19,18,17,16,15,14,13,12,11, \
    10,9,8,7,6,5,4,3,2,1))

// 对每个字段执行宏 OP
#define QJ_TO_1(OP, x)        OP(x)
#define QJ_TO_2(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_1(OP, __VA_ARGS__))
#define QJ_TO_3(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_2(OP, __VA_ARGS__))
#define QJ_TO_4(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_3(OP, __VA_ARGS__))
#define QJ_TO_5(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_4(OP, __VA_ARGS__))
#define QJ_TO_6(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_5(OP, __VA_ARGS__))
#define QJ_TO_7(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_6(OP, __VA_ARGS__))
#define QJ_TO_8(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_7(OP, __VA_ARGS__))
#define QJ_TO_9(OP, x, ...)   OP(x) QJ_EXPAND(QJ_TO_8(OP, __VA_ARGS__))
#define QJ_TO_10(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_9(OP, __VA_ARGS__))
#define QJ_TO_11(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_10(OP, __VA_ARGS__))
#define QJ_TO_12(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_11(OP, __VA_ARGS__))
#define QJ_TO_13(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_12(OP, __VA_ARGS__))
#define QJ_TO_14(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_13(OP, __VA_ARGS__))
#define QJ_TO_15(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_14(OP, __VA_ARGS__))
#define QJ_TO_16(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_15(OP, __VA_ARGS__))
#define QJ_TO_17(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_16(OP, __VA_ARGS__))
#define QJ_TO_18(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_17(OP, __VA_ARGS__))
#define QJ_TO_19(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_18(OP, __VA_ARGS__))
#define QJ_TO_20(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_19(OP, __VA_ARGS__))
#define QJ_TO_21(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_20(OP, __VA_ARGS__))
#define QJ_TO_22(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_21(OP, __VA_ARGS__))
#define QJ_TO_23(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_22(OP, __VA_ARGS__))
#define QJ_TO_24(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_23(OP, __VA_ARGS__))
#define QJ_TO_25(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_24(OP, __VA_ARGS__))
#define QJ_TO_26(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_25(OP, __VA_ARGS__))
#define QJ_TO_27(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_26(OP, __VA_ARGS__))
#define QJ_TO_28(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_27(OP, __VA_ARGS__))
#define QJ_TO_29(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_28(OP, __VA_ARGS__))
#define QJ_TO_30(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_29(OP, __VA_ARGS__))
#define QJ_TO_31(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_30(OP, __VA_ARGS__))
#define QJ_TO_32(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_31(OP, __VA_ARGS__))
#define QJ_TO_33(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_32(OP, __VA_ARGS__))
#define QJ_TO_34(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_33(OP, __VA_ARGS__))
#define QJ_TO_35(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_34(OP, __VA_ARGS__))
#define QJ_TO_36(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_35(OP, __VA_ARGS__))
#define QJ_TO_37(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_36(OP, __VA_ARGS__))
#define QJ_TO_38(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_37(OP, __VA_ARGS__))
#define QJ_TO_39(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_38(OP, __VA_ARGS__))
#define QJ_TO_40(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_39(OP, __VA_ARGS__))
#define QJ_TO_41(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_40(OP, __VA_ARGS__))
#define QJ_TO_42(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_41(OP, __VA_ARGS__))
#define QJ_TO_43(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_42(OP, __VA_ARGS__))
#define QJ_TO_44(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_43(OP, __VA_ARGS__))
#define QJ_TO_45(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_44(OP, __VA_ARGS__))
#define QJ_TO_46(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_45(OP, __VA_ARGS__))
#define QJ_TO_47(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_46(OP, __VA_ARGS__))
#define QJ_TO_48(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_47(OP, __VA_ARGS__))
#define QJ_TO_49(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_48(OP, __VA_ARGS__))
#define QJ_TO_50(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_49(OP, __VA_ARGS__))
#define QJ_TO_51(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_50(OP, __VA_ARGS__))
#define QJ_TO_52(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_51(OP, __VA_ARGS__))
#define QJ_TO_53(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_52(OP, __VA_ARGS__))
#define QJ_TO_54(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_53(OP, __VA_ARGS__))
#define QJ_TO_55(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_54(OP, __VA_ARGS__))
#define QJ_TO_56(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_55(OP, __VA_ARGS__))
#define QJ_TO_57(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_56(OP, __VA_ARGS__))
#define QJ_TO_58(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_57(OP, __VA_ARGS__))
#define QJ_TO_59(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_58(OP, __VA_ARGS__))
#define QJ_TO_60(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_59(OP, __VA_ARGS__))
#define QJ_TO_61(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_60(OP, __VA_ARGS__))
#define QJ_TO_62(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_61(OP, __VA_ARGS__))
#define QJ_TO_63(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_62(OP, __VA_ARGS__))
#define QJ_TO_64(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_63(OP, __VA_ARGS__))
#define QJ_TO_65(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_64(OP, __VA_ARGS__))
#define QJ_TO_66(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_65(OP, __VA_ARGS__))
#define QJ_TO_67(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_66(OP, __VA_ARGS__))
#define QJ_TO_68(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_67(OP, __VA_ARGS__))
#define QJ_TO_69(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_68(OP, __VA_ARGS__))
#define QJ_TO_70(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_69(OP, __VA_ARGS__))
#define QJ_TO_71(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_70(OP, __VA_ARGS__))
#define QJ_TO_72(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_71(OP, __VA_ARGS__))
#define QJ_TO_73(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_72(OP, __VA_ARGS__))
#define QJ_TO_74(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_73(OP, __VA_ARGS__))
#define QJ_TO_75(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_74(OP, __VA_ARGS__))
#define QJ_TO_76(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_75(OP, __VA_ARGS__))
#define QJ_TO_77(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_76(OP, __VA_ARGS__))
#define QJ_TO_78(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_77(OP, __VA_ARGS__))
#define QJ_TO_79(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_78(OP, __VA_ARGS__))
#define QJ_TO_80(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_79(OP, __VA_ARGS__))
#define QJ_TO_81(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_80(OP, __VA_ARGS__))
#define QJ_TO_82(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_81(OP, __VA_ARGS__))
#define QJ_TO_83(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_82(OP, __VA_ARGS__))
#define QJ_TO_84(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_83(OP, __VA_ARGS__))
#define QJ_TO_85(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_84(OP, __VA_ARGS__))
#define QJ_TO_86(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_85(OP, __VA_ARGS__))
#define QJ_TO_87(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_86(OP, __VA_ARGS__))
#define QJ_TO_88(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_87(OP, __VA_ARGS__))
#define QJ_TO_89(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_88(OP, __VA_ARGS__))
#define QJ_TO_90(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_89(OP, __VA_ARGS__))
#define QJ_TO_91(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_90(OP, __VA_ARGS__))
#define QJ_TO_92(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_91(OP, __VA_ARGS__))
#define QJ_TO_93(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_92(OP, __VA_ARGS__))
#define QJ_TO_94(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_93(OP, __VA_ARGS__))
#define QJ_TO_95(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_94(OP, __VA_ARGS__))
#define QJ_TO_96(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_95(OP, __VA_ARGS__))
#define QJ_TO_97(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_96(OP, __VA_ARGS__))
#define QJ_TO_98(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_97(OP, __VA_ARGS__))
#define QJ_TO_99(OP, x, ...)  OP(x) QJ_EXPAND(QJ_TO_98(OP, __VA_ARGS__))
#define QJ_TO_100(OP, x, ...) OP(x) QJ_EXPAND(QJ_TO_99(OP, __VA_ARGS__))
// 需要更多请按规律继续添加...

#define QJ_FOR_EACH_(N, OP, ...) QJ_EXPAND(QJ_CONCAT(QJ_TO_, N)(OP, __VA_ARGS__))
#define QJ_FOR_EACH(OP, ...) QJ_FOR_EACH_(QJ_COUNT(__VA_ARGS__), OP, __VA_ARGS__)

// 单个字段的写/读
#define QJ_WRITE_FIELD(field)  __obj.insert(QStringLiteral(#field), QJsonConvert::toJson(field));
#define QJ_READ_FIELD(field)   QJsonConvert::fromJson(__obj.value(QStringLiteral(#field)), field);


// ============ 用户使用的宏 ============
#define Q_JSON_DEFINE_TYPE(Type, ...)                                  \
    QJsonObject toJson() const {                                       \
        QJsonObject __obj;                                             \
        QJ_FOR_EACH(QJ_WRITE_FIELD, __VA_ARGS__)                       \
        return __obj;                                                  \
    }                                                                  \
    QString toJsonString(QJsonDocument::JsonFormat fmt =               \
                           QJsonDocument::Compact) const {             \
        return QString(QJsonDocument(toJson()).toJson(fmt));           \
    }                                                                  \
    QByteArray toJsonBytes(QJsonDocument::JsonFormat fmt =             \
                           QJsonDocument::Compact) const {             \
        return QJsonDocument(toJson()).toJson(fmt);                    \
    }                                                                  \
    void fromJson(const QJsonObject& __obj) {                          \
        QJ_FOR_EACH(QJ_READ_FIELD, __VA_ARGS__)                        \
    }                                                                  \
    void fromJson(const QByteArray& data) {                            \
        fromJson(QJsonDocument::fromJson(data).object());              \
    }                                                                  \
    void fromJson(const QString& data) {                               \
        fromJson(QJsonDocument::fromJson(data.toUtf8()).object());     \
    }                                                                  \
    static Type fromJsonBytes(const QByteArray& data) {                \
        Type t; t.fromJson(QJsonDocument::fromJson(data).object());    \
        return t;                                                      \
    }

演示

cpp 复制代码
struct Address {
    QString city;
    QString street;
    int zip = 0;
    std::array<int,3> a={1,2,3};
    Q_JSON_DEFINE_TYPE(Address, city, street, zip,a)
};

struct Person {
    QString name;
    int age = 0;
    double score = 0.0;
    bool vip = false;
    QVector<QString> hobbies;
    Address address;          // 嵌套自定义类型
    QList<Address> history;   // 自定义类型容器
    Q_JSON_DEFINE_TYPE(Person, name, age, score, vip, hobbies, address, history)
};

Person p;
qDebug().noquote().nospace()<<p.toJsonString(QJsonDocument::Indented);
相关推荐
一只很酸de橘子1 小时前
PostgreSQL 生成 JSON 字符串
postgresql·json
AiTop1002 小时前
Claude Code 推出 Agent View:命令行编程正式进入“多线程并发“时代
开发语言·人工智能·ai·aigc
jf加菲猫2 小时前
第21章 Qt WebEngine
开发语言·c++·qt·ui
码农-阿杰2 小时前
深入理解 synchronized 底层实现:从 HotSpot C++ 源码看对象锁与 Monitor 机制
开发语言·c++·
2401_832298102 小时前
AI智能体监管落地,OpenClaw率先建立行业合规标准
开发语言
geovindu3 小时前
go: Lock/Mutex Pattern
开发语言·后端·设计模式·golang·互斥锁模式
知识分享小能手3 小时前
R语言入门学习教程,从入门到精通,R语言日期和时间序列(6)
开发语言·学习·r语言
叼烟扛炮3 小时前
C++ 知识点18 内部类
开发语言·c++·算法·内部类
TAN-90°-4 小时前
Java 3——getter和setter super()关键字
java·开发语言