refs #721 Use QLatin1String for JSON object keys (disabled until Qt 5.7.1).

This commit is contained in:
Mathew Sutcliffe
2016-08-23 17:14:37 +01:00
parent e2e1e53d42
commit 8b1bdbdcf8
3 changed files with 152 additions and 5 deletions

View File

@@ -308,6 +308,80 @@ QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QByteA
return json; return json;
} }
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const int &> &value)
{
json[value.first] = QJsonValue(value.second);
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const qint16 &> &value)
{
json[value.first] = QJsonValue(value.second);
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const qulonglong &> &value)
{
json[value.first] = QJsonValue(static_cast<int>(value.second));
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const qlonglong &> &value)
{
json[value.first] = QJsonValue(value.second);
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const uint &> &value)
{
json[value.first] = QJsonValue(static_cast<int>(value.second));
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QString &> &value)
{
json[value.first] = QJsonValue(value.second);
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QStringList &> &value)
{
json[value.first] = QJsonValue(QJsonArray::fromStringList(value.second));
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const double &> &value)
{
json[value.first] = QJsonValue(value.second);
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const bool &> &value)
{
json[value.first] = QJsonValue(value.second);
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QDateTime &> &value)
{
json[value.first] = QJsonValue(value.second.toString());
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QPixmap &> &value)
{
QString pm(BlackMisc::pixmapToPngHexString(value.second));
json[value.first] = pm;
return json;
}
QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QByteArray &> &value)
{
QString pm(BlackMisc::bytesToHexString(value.second));
json[value.first] = pm;
return json;
}
namespace BlackMisc namespace BlackMisc
{ {
namespace Json namespace Json

View File

@@ -28,10 +28,44 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#if QT_VERSION >= 0x50701
#define BLACK_USE_LATIN1_JSON_KEYS
#endif
class QDateTime; class QDateTime;
class QPixmap; class QPixmap;
class QStringList; 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 * \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 //! \brief Specialized JSON serialization for enum
//! \remarks needs to be in global namespace //! \remarks needs to be in global namespace
//! \ingroup JSON //! \ingroup JSON
//! @{
template<class ENUM> template<class ENUM>
std::enable_if_t<std::is_enum<ENUM>::value, QJsonObject> std::enable_if_t<std::is_enum<ENUM>::value, QJsonObject>
&operator<<(QJsonObject &json, std::pair<QString, const ENUM &> value) &operator<<(QJsonObject &json, std::pair<QString, const ENUM &> value)
@@ -76,15 +111,31 @@ std::enable_if_t<std::is_enum<ENUM>::value, QJsonObject>
json.insert(value.first, QJsonValue(static_cast<int>(value.second))); json.insert(value.first, QJsonValue(static_cast<int>(value.second)));
return json; return json;
} }
template<class ENUM>
std::enable_if_t<std::is_enum<ENUM>::value, QJsonObject>
&operator<<(QJsonObject &json, std::pair<BlackMisc::CExplicitLatin1String, const ENUM &> value)
{
json[value.first] = QJsonValue(static_cast<int>(value.second));
return json;
}
//! @}
//! \brief Specialized JSON serialization for QFlags generated enum //! \brief Specialized JSON serialization for QFlags generated enum
//! \ingroup JSON //! \ingroup JSON
//! @{
template<class ENUM> template<class ENUM>
QJsonObject &operator<<(QJsonObject &json, std::pair<QString, const QFlags<ENUM> &> value) QJsonObject &operator<<(QJsonObject &json, std::pair<QString, const QFlags<ENUM> &> value)
{ {
json.insert(value.first, QJsonValue(static_cast<int>(value.second))); json.insert(value.first, QJsonValue(static_cast<int>(value.second)));
return json; return json;
} }
template<class ENUM>
QJsonObject &operator<<(QJsonObject &json, std::pair<BlackMisc::CExplicitLatin1String, const QFlags<ENUM> &> value)
{
json[value.first] = QJsonValue(static_cast<int>(value.second));
return json;
}
//! @}
//! \brief Specialized JSON deserialization for enum //! \brief Specialized JSON deserialization for enum
//! \ingroup JSON //! \ingroup JSON
@@ -173,6 +224,18 @@ BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QStr
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QDateTime &> &value); BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QDateTime &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QPixmap &> &value); BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QPixmap &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QByteArray &> &value); BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QByteArray &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const int &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const qint16 &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const qlonglong &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const uint &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const qulonglong &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QString &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QStringList &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const double &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const bool &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QDateTime &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QPixmap &> &value);
BLACKMISC_EXPORT QJsonObject &operator<<(QJsonObject &json, const std::pair<BlackMisc::CExplicitLatin1String, const QByteArray &> &value);
//! @} //! @}
namespace BlackMisc namespace BlackMisc
@@ -268,6 +331,13 @@ namespace BlackMisc
json.insert(value.first, QJsonValue(value.second.toJson())); json.insert(value.first, QJsonValue(value.second.toJson()));
return json; return json;
} }
//! operator << for JSON
friend QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const Derived &> &value)
{
json[value.first] = QJsonValue(value.second.toJson());
return json;
}
}; };
/*! /*!
@@ -284,9 +354,9 @@ namespace BlackMisc
{ {
QJsonObject json; QJsonObject json;
auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>()); auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>());
meta.forEachMemberName(*derived(), [ & ](const auto & member, const QString & name) meta.forEachMemberName(*derived(), [ & ](const auto & member, CExplicitLatin1String name)
{ {
json << std::pair<QString, const std::decay_t<decltype(member)> &>(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<const TBaseOfT<Derived> *>(derived()))); return Json::appendJsonObject(json, baseToJson(static_cast<const TBaseOfT<Derived> *>(derived())));
} }
@@ -303,7 +373,7 @@ namespace BlackMisc
{ {
baseConvertFromJson(static_cast<TBaseOfT<Derived> *>(derived()), json); baseConvertFromJson(static_cast<TBaseOfT<Derived> *>(derived()), json);
auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>()); auto meta = introspect<Derived>().without(MetaFlags<DisabledForJson>());
meta.forEachMemberName(*derived(), [ & ](auto & member, const QString & name) meta.forEachMemberName(*derived(), [ & ](auto & member, CExplicitLatin1String name)
{ {
auto it = json.find(name); auto it = json.find(name);
if (it != json.end()) { it.value() >> member; } if (it != json.end()) { it.value() >> member; }

View File

@@ -124,6 +124,9 @@ namespace BlackMisc
{ {
return Private::invoke(m_ptr, std::forward<T>(object), std::forward<Ts>(args)...); return Private::invoke(m_ptr, std::forward<T>(object), std::forward<Ts>(args)...);
} }
//! Return name as QLatin1String.
Q_DECL_CONSTEXPR auto latin1Name() const { return QLatin1String(m_name); }
}; };
/*! /*!
@@ -241,12 +244,12 @@ namespace BlackMisc
template <typename F> template <typename F>
static void forEachMemberName(T &object, F &&visitor) static void forEachMemberName(T &object, F &&visitor)
{ {
forEachImpl([ & ](auto &&member, auto) { std::forward<F>(visitor)(member.in(object), QString(member.m_name)); }); forEachImpl([ & ](auto &&member, auto) { std::forward<F>(visitor)(member.in(object), member.latin1Name()); });
} }
template <typename F> template <typename F>
static void forEachMemberName(const T &object, F &&visitor) static void forEachMemberName(const T &object, F &&visitor)
{ {
forEachImpl([ & ](auto &&member, auto) { std::forward<F>(visitor)(member.in(object), QString(member.m_name)); }); forEachImpl([ & ](auto &&member, auto) { std::forward<F>(visitor)(member.in(object), member.latin1Name()); });
} }
//! @} //! @}