让nlohmann json支持std::wstring和嵌套结构的序列化与反序列化
nlohmann json是一个star很高的C++ json解析库。
要让nlohmann json支持某个类型T,只要给这个类型T实现一个偏特化的struct adl_serializer<T>即可。adl_serializer是这个库里面针对泛型T预定义的适配器。
对于std::optional,也是要增加偏特化。
template <typename T>
struct adl_serializer<std::optional<T>> {
static void to_json(json& j, const std::optional<T>& opt) {
if (opt == std::nullopt) {
j = nullptr;
} else {
j = *opt;
}
}
static void from_json(const json& j, std::optional<T>& opt) {
if (j.is_null()) {
opt = std::nullopt;
} else {
opt = j.get<T>();
}
}
};
而嵌套结构,本身就支持的。使用预定义的宏NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE,可以免去自己针对每个类型T要实现其from_json/to_json函数。
下面是一个例子,适用于VC++。里面UTF-8和UTF-16的转换可以自行换成其他的实现方式。
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
#include <string>
#include <codecvt>
#include <locale>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace nlohmann {
template <>
struct adl_serializer<std::wstring> {
static void to_json(json& j, const std::wstring& str) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
j = converter.to_bytes(str);
}
static void from_json(const json& j, std::wstring& str) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
str = converter.from_bytes(j.get<std::string>());
}
};
}
namespace ns {
struct Address {
std::wstring country;
std::wstring province;
std::wstring city;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Address, country, province, city)
struct Person {
std::wstring name;
Address address;
int age;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Person, name, address, age)
}
int main(int argc, char* argv[], char* envp)
{
ns::Person p{ L"匿名", { L"中国", L"湖北", L"武汉" }, 60 };
json j = p;
const auto s = j.dump();
auto p2 = j.template get<ns::Person>();
return 0;
}