diff --git a/src/blackmisc/json.cpp b/src/blackmisc/json.cpp index cc889498a..82312c317 100644 --- a/src/blackmisc/json.cpp +++ b/src/blackmisc/json.cpp @@ -308,6 +308,80 @@ QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(static_cast(value.second)); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(static_cast(value.second)); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(QJsonArray::fromStringList(value.second)); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + json[value.first] = QJsonValue(value.second.toString()); + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + QString pm(BlackMisc::pixmapToPngHexString(value.second)); + json[value.first] = pm; + return json; +} + +QJsonObject &operator<<(QJsonObject &json, const std::pair &value) +{ + QString pm(BlackMisc::bytesToHexString(value.second)); + json[value.first] = pm; + return json; +} + namespace BlackMisc { namespace Json diff --git a/src/blackmisc/json.h b/src/blackmisc/json.h index 243f7184a..63ff7d2c7 100644 --- a/src/blackmisc/json.h +++ b/src/blackmisc/json.h @@ -28,10 +28,44 @@ #include #include +#if QT_VERSION >= 0x50701 +#define BLACK_USE_LATIN1_JSON_KEYS +#endif + class QDateTime; class QPixmap; class QStringList; +namespace BlackMisc +{ + /*! + * Simple literal type containing a single QLatin1String. + * + * Just useful for encapsulating a QLatin1String in a way that inhibits implicit conversion to QString + * to avoid ambiguities in overload resolution. + */ + struct CExplicitLatin1String + { + //! Embedded string. + const QLatin1String m_latin1; + + //! Implicit constructor. + Q_DECL_CONSTEXPR CExplicitLatin1String(QLatin1String s) : m_latin1(s) {} + +#ifdef BLACK_USE_LATIN1_JSON_KEYS + //! Type usable as key in QJsonObject. + Q_DECL_CONSTEXPR auto toJsonKey() const { return *this; } + //! Implicit conversion. + Q_DECL_CONSTEXPR operator QLatin1String() const { return m_latin1; } +#else + //! Type usable as key in QJsonObject. + QString toJsonKey() const { return m_latin1; } + //! Implicit conversion. + operator QString() const { return m_latin1; } +#endif + }; +} + /*! * \defgroup JSON Streaming operators for JSON */ @@ -69,6 +103,7 @@ BLACKMISC_EXPORT const QJsonValueRef &operator >>(const QJsonValueRef &json, QBy //! \brief Specialized JSON serialization for enum //! \remarks needs to be in global namespace //! \ingroup JSON +//! @{ template std::enable_if_t::value, QJsonObject> &operator<<(QJsonObject &json, std::pair value) @@ -76,15 +111,31 @@ std::enable_if_t::value, QJsonObject> json.insert(value.first, QJsonValue(static_cast(value.second))); return json; } +template +std::enable_if_t::value, QJsonObject> +&operator<<(QJsonObject &json, std::pair value) +{ + json[value.first] = QJsonValue(static_cast(value.second)); + return json; +} +//! @} //! \brief Specialized JSON serialization for QFlags generated enum //! \ingroup JSON +//! @{ template QJsonObject &operator<<(QJsonObject &json, std::pair &> value) { json.insert(value.first, QJsonValue(static_cast(value.second))); return json; } +template +QJsonObject &operator<<(QJsonObject &json, std::pair &> value) +{ + json[value.first] = QJsonValue(static_cast(value.second)); + return json; +} +//! @} //! \brief Specialized JSON deserialization for enum //! \ingroup JSON @@ -173,6 +224,18 @@ BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); +BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair &value); //! @} namespace BlackMisc @@ -268,6 +331,13 @@ namespace BlackMisc json.insert(value.first, QJsonValue(value.second.toJson())); return json; } + + //! operator << for JSON + friend QJsonObject &operator<<(QJsonObject &json, const std::pair &value) + { + json[value.first] = QJsonValue(value.second.toJson()); + return json; + } }; /*! @@ -284,9 +354,9 @@ namespace BlackMisc { QJsonObject json; auto meta = introspect().without(MetaFlags()); - meta.forEachMemberName(*derived(), [ & ](const auto & member, const QString & name) + meta.forEachMemberName(*derived(), [ & ](const auto & member, CExplicitLatin1String name) { - json << std::pair &>(name, member); // std::make_pair causes an ambiguous operator<< + json << std::make_pair(name.toJsonKey(), std::cref(member)); }); return Json::appendJsonObject(json, baseToJson(static_cast *>(derived()))); } @@ -303,7 +373,7 @@ namespace BlackMisc { baseConvertFromJson(static_cast *>(derived()), json); auto meta = introspect().without(MetaFlags()); - meta.forEachMemberName(*derived(), [ & ](auto & member, const QString & name) + meta.forEachMemberName(*derived(), [ & ](auto & member, CExplicitLatin1String name) { auto it = json.find(name); if (it != json.end()) { it.value() >> member; } diff --git a/src/blackmisc/metaclass.h b/src/blackmisc/metaclass.h index dccc93c05..063409709 100644 --- a/src/blackmisc/metaclass.h +++ b/src/blackmisc/metaclass.h @@ -124,6 +124,9 @@ namespace BlackMisc { return Private::invoke(m_ptr, std::forward(object), std::forward(args)...); } + + //! Return name as QLatin1String. + Q_DECL_CONSTEXPR auto latin1Name() const { return QLatin1String(m_name); } }; /*! @@ -241,12 +244,12 @@ namespace BlackMisc template static void forEachMemberName(T &object, F &&visitor) { - forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object), QString(member.m_name)); }); + forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object), member.latin1Name()); }); } template static void forEachMemberName(const T &object, F &&visitor) { - forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object), QString(member.m_name)); }); + forEachImpl([ & ](auto &&member, auto) { std::forward(visitor)(member.in(object), member.latin1Name()); }); } //! @}