如何在 C++ 中 serialize/deserialize std::map<int, MyObject> to/from json
How to serialize/deserialize std::map<int, MyObject> to/from json in C++
我正在尝试 serialize/deserialize std::map<int, MyObject>
使用 https://github.com/nlohmann/json
它说 here 地图的键必须能够生成 std::string
。我怎样才能做到这一点?
实现转换的基本用法 to/from 我的自定义对象 MyObject
将是:
using nlohmann::json;
namespace ns {
void to_json(json& j, const MyObject& p) {
j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};
}
void from_json(const json& j, MyObject& p) {
j.at("name").get_to(p.name);
j.at("address").get_to(p.address);
j.at("age").get_to(p.age);
}
} // namespace ns
但是我应该为地图做什么?我最不想做的就是实现 void to_json(json& j, const std::map<int, MyObject>& p)
和 void from_json(const json& j, std::map<int, MyObject>& p)
。由于库已经支持 std::map
,它应该为我做所有事情,我只需要将 int
转换为 std::string
。我该怎么做?
自述文件中的措辞清楚地说明了为什么这不起作用(强调我的):
Likewise, any associative key-value containers ... whose keys can construct an std::string
and whose values can be used to construct JSON values ... can be used to create a JSON object.
这就是为什么使用 int
作为键不适用于此库的原因;不能从 int
.
构造 std::string
自然的 follow-up 问题是 为什么 这是不允许的。这是你必须向图书馆的作者寻求明确答案的事情。
我们可以推测这是因为没有一种方法可以将整数转换为字符串。也许假设没有前导零的 10 进制表示是一个合理的选择,但没有令人信服的理由说明为什么这必须是唯一的选择。
hex-encoded 字符串、科学计数法、千位分隔符或任何可能数量的其他选项呢?
另一个可能的原因是整数键暗示一个稀疏数组,因此可能不清楚您请求在输出中生成对象还是数组。
一个可能的解决方案是构建一个助手,通过 运行 键通过 std::to_string()
:
将任何映射转换为 std::map<std::string, TValue>
// Copy variant
template <typename T>
std::map<std::string, typename T::mapped_type> to_string_keyed_map(T const & input) {
std::map<std::string, typename T::mapped_type> output;
for (auto const & pair : input) {
output.emplace(std::to_string(pair.first), pair.second);
}
return output;
}
// Move variant
template <typename T>
std::map<std::string, typename T::mapped_type> to_string_keyed_map(T && input) {
std::map<std::string, typename T::mapped_type> output;
for (auto & pair : input) {
output.emplace(std::to_string(pair.first), std::move(pair.second));
}
return output;
}
我正在尝试 serialize/deserialize std::map<int, MyObject>
使用 https://github.com/nlohmann/json
它说 here 地图的键必须能够生成 std::string
。我怎样才能做到这一点?
实现转换的基本用法 to/from 我的自定义对象 MyObject
将是:
using nlohmann::json;
namespace ns {
void to_json(json& j, const MyObject& p) {
j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};
}
void from_json(const json& j, MyObject& p) {
j.at("name").get_to(p.name);
j.at("address").get_to(p.address);
j.at("age").get_to(p.age);
}
} // namespace ns
但是我应该为地图做什么?我最不想做的就是实现 void to_json(json& j, const std::map<int, MyObject>& p)
和 void from_json(const json& j, std::map<int, MyObject>& p)
。由于库已经支持 std::map
,它应该为我做所有事情,我只需要将 int
转换为 std::string
。我该怎么做?
自述文件中的措辞清楚地说明了为什么这不起作用(强调我的):
Likewise, any associative key-value containers ... whose keys can construct an
std::string
and whose values can be used to construct JSON values ... can be used to create a JSON object.
这就是为什么使用 int
作为键不适用于此库的原因;不能从 int
.
std::string
自然的 follow-up 问题是 为什么 这是不允许的。这是你必须向图书馆的作者寻求明确答案的事情。
我们可以推测这是因为没有一种方法可以将整数转换为字符串。也许假设没有前导零的 10 进制表示是一个合理的选择,但没有令人信服的理由说明为什么这必须是唯一的选择。
hex-encoded 字符串、科学计数法、千位分隔符或任何可能数量的其他选项呢?
另一个可能的原因是整数键暗示一个稀疏数组,因此可能不清楚您请求在输出中生成对象还是数组。
一个可能的解决方案是构建一个助手,通过 运行 键通过 std::to_string()
:
std::map<std::string, TValue>
// Copy variant
template <typename T>
std::map<std::string, typename T::mapped_type> to_string_keyed_map(T const & input) {
std::map<std::string, typename T::mapped_type> output;
for (auto const & pair : input) {
output.emplace(std::to_string(pair.first), pair.second);
}
return output;
}
// Move variant
template <typename T>
std::map<std::string, typename T::mapped_type> to_string_keyed_map(T && input) {
std::map<std::string, typename T::mapped_type> output;
for (auto & pair : input) {
output.emplace(std::to_string(pair.first), std::move(pair.second));
}
return output;
}