代码实现部分
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);