目录
代码
#include <QString>
#include <QVector>
#include <QMap>
NLOHMANN_JSON_NAMESPACE_BEGIN
template <>
struct adl_serializer<QString> {
static void to_json(json& j, const QString& opt) {
j = opt.toStdString();
}
static void from_json(const json& j, QString& opt) {
opt = QString::fromStdString(j.template get<std::string>());
}
};
template <typename T>
struct adl_serializer<QVector<T>> {
static void to_json(json& j, const QVector<T>& opt) {
#if QT_DEPRECATED_SINCE(5, 14) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
j = std::vector<T>(opt.begin(), opt.end());
#else
j = opt.toStdVector();
#endif
}
static void from_json(const json& j, QVector<T>& opt) {
#if QT_DEPRECATED_SINCE(5, 14) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
const auto& _vector = j.template get<std::vector<T>>();
opt = QVector<T>(_vector.cbegin(), _vector.cend());
#else
opt = QVector<T>::fromStdVector(j.template get<std::vector<T>>());
#endif
}
};
template <typename Key,typename T>
struct adl_serializer<QMap<Key,T>> {
static void to_json(json& j, const QMap<Key, T>& opt) {
j = opt.toStdMap();
}
static void from_json(const json& j, QMap<Key, T> &opt) {
opt = QMap<Key, T>(j.template get<std::map<Key, T>>());
}
};
NLOHMANN_JSON_NAMESPACE_END
- 加在
json.hpp
要注意在唯一定义之间
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
#define INCLUDE_NLOHMANN_JSON_HPP_
.....
#endif // INCLUDE_NLOHMANN_JSON_HPP_
- 加在外侧
原理
官方原文
How do I convert third-party types?
如何转换第三方类型?
This requires a bit more advanced technique. But first, let’s see how this conversion mechanism works:
这需要更先进的技术。但首先,让我们看看这个转换机制是如何工作的:
The library uses JSON Serializers to convert types to json. The default serializer for nlohmann::json is nlohmann::adl_serializer (ADL means Argument-Dependent Lookup).
该库使用JSON序列化器将类型转换为json。nlohmann::json的默认序列化器是nlohmann::adl_serializer(ADL表示参数依赖的序列化器(实参依赖查找)。
It is implemented like this (simplified):
它是这样实现的(简化的):
template <typename T>
struct adl_serializer {
static void to_json(json& j, const T& value) {
// calls the "to_json" method in T's namespace
}
static void from_json(const json& j, T& value) {
// same thing, but with the "from_json" method
}
};
This serializer works fine when you have control over the type’s namespace. However, what about boost::optional
or std::filesystem::path
(C++17)? Hijacking the boost namespace is pretty bad, and it’s illegal to add something other than template specializations to std…
当您可以控制类型的命名空间时,此序列化程序可以正常工作。但是,
boost::optional
或std::filesystem::path
(C++17)呢?劫持boost命名空间是非常糟糕的,并且向std添加除了模板专门化之外的东西是非法的。
To solve this, you need to add a specialization of adl_serializer to
the nlohmann
namespace, here’s an example:
为了解决这个问题,你需要将adl_serializer
的特殊化添加到nlohmann
命名空间,这里有一个例子:
// partial specialization (full specialization works too)
// 部分专业化(完全专业化也可以)
NLOHMANN_JSON_NAMESPACE_BEGIN
template <typename T>
struct adl_serializer<boost::optional<T>> {
static void to_json(json& j, const boost::optional<T>& opt) {
if (opt == boost::none) {
j = nullptr;
} else {
j = *opt; // this will call adl_serializer<T>::to_json which will
// find the free function to_json in T's namespace!
}
}
static void from_json(const json& j, boost::optional<T>& opt) {
if (j.is_null()) {
opt = boost::none;
} else {
opt = j.template get<T>(); // same as above, but with
// adl_serializer<T>::from_json
}
}
};
NLOHMANN_JSON_NAMESPACE_END
- ABI compatibility ABI兼容性
UseNLOHMANN_JSON_NAMESPACE_BEGIN
andNLOHMANN_JSON_NAMESPACE_END
instead ofnamespace nlohmann { }
in code which may be linked with different versions of this library.
在可能与该库的不同版本链接的代码中使用NLOHMANN_JSON_NAMESPACE_BEGIN
和NLOHMANN_JSON_NAMESPACE_END
而不是命名空间namespace nlohmann{}
。
How can I use get() for non-default constructible/non-copyable types?
如何将
get()
用于非默认的可构造/不可复制类型?
There is a way, if your type is MoveConstructible. You will need to specialize the adl_serializer
as well, but with a special from_json
overload:
如果你的类型是 C++ 具名要求:可移动构造 (MoveConstructible),有一种方法。你还需要专门化adl_serializer
,但是要使用一个特殊的from_json
重载:
struct move_only_type {
move_only_type() = delete;
move_only_type(int ii): i(ii) {}
move_only_type(const move_only_type&) = delete;
move_only_type(move_only_type&&) = default;
int i;
};
namespace nlohmann {
template <>
struct adl_serializer<move_only_type> {
// note: the return type is no longer 'void', and the method only takes
// one argument
/*注意:返回类型不再是'void',方法只接受一个参数*/
static move_only_type from_json(const json& j) {
return {j.template get<int>()};
}
// Here's the catch! You must provide a to_json method! Otherwise, you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
/*这是陷阱!你必须提供一个to_json方法!否则你将无法将move_only_type转换为json,
因为您完全该类型的专用adl_serializer*/
static void to_json(json& j, move_only_type t) {
j = t.i;
}
};
}
原文图