C++ 如何序列化/反序列化std::map<;int,MyObject>;与C+中的json之间的通信+;
我正在尝试使用 它表示映射的键必须能够生成C++ 如何序列化/反序列化std::map<;int,MyObject>;与C+中的json之间的通信+;,c++,json,c++11,nlohmann-json,C++,Json,C++11,Nlohmann Json,我正在尝试使用 它表示映射的键必须能够生成std::string。我怎样才能做到这一点 实现与自定义对象的转换的基本用法是: using nlohmann::json; namespace ns { void to_json(json& j, const MyObject& p) { j = json{{"name", p.name}, {"address", p.address}, {"age"
std::string
。我怎样才能做到这一点
实现与自定义对象的转换的基本用法是:
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&p)
和void from_json(const json&j,std::map&p)
。由于库已经支持std::map
,它应该可以为我做一切,我只需要将int
转换为std::string
。我怎样才能做到这一点呢?自述文件中的措辞清楚地说明了这一点不起作用的原因(重点是我的):
同样,任何关联键值容器。。。其键可以构造std::string
,其值可以用于构造JSON值。。。可用于创建JSON对象
这就是为什么使用int
作为键不适用于此库的原因;无法从int
构造std::string
自然的后续问题是为什么这是不允许的。这是你必须向图书馆的作者寻求明确答案的事情 我们可以推测这是因为没有一种方法可以将积分转换成字符串。也许假设一个不带前导零的10进制表示是一个合理的选择,但没有令人信服的理由说明这是唯一的选择 十六进制编码的字符串、科学记数法、数千个分隔符或任何可能的其他选项呢 另一个可能的原因是整数键表示稀疏数组,因此可能不清楚您是请求在输出中生成对象还是数组
一个可能的解决方案是构建一个助手,通过运行
std::to_string()
,将任何映射转换为std::map
:
//复制变量
模板
映射到字符串键控映射(T常量和输入){
地图输出;
用于(自动常量和对:输入){
放置(std::to_字符串(pair.first),pair.second);
}
返回输出;
}
//移动变体
模板
映射到字符串键控映射(T&&input){
地图输出;
用于(自动配对:输入(&P){
emplace(std::to_string(pair.first),std::move(pair.second));
}
返回输出;
}
不熟悉该特定库,但一个特定的解决方法是为int
值提供一个轻量级包装,该值还实现了运算符std::string
。这似乎是一个奇怪的限制。根据文档,映射值为整数不是问题,它将序列化它们。我无法立即看出在json中使用int
s作为映射/列表键的问题。文档中的关键措辞是“谁的键可以构造std::string
”。没有接受int
值的std::string
构造函数,这就是它不起作用的原因。@SamVarshavchik值为整数不是问题,因为JSON具有本机数字类型。这种情况必须得到处理,才能使实施变得有意义。但是,对象键不能是整数;它们一定是弦。库作者显然选择要求键可以显式转换为<代码> STD::String ,但是在C++ <代码> int <代码>中没有显式转换为// 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;
}