如何在C ++中向json序列化/反序列化std :: map <int,MyObject>

问题描述

我正在尝试使用https://github.com/nlohmann/jsonstd::map<int,MyObject>进行序列化/反序列化

它告诉here,该地图的键必须能够生成std::string。我该如何实现?

实现与自定义对象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。我该怎么办?

解决方法

自述文件中的措词很清楚,为什么它不起作用(强调我的意思):

同样,任何关联的键值容器...其键可以构造一个std::string,并且其值可用于构造JSON值...可用于创建一个JSON对象。

这就是为什么使用int作为键对此库不起作用的原因; std::string不能从int构造。


自然的后续问题是为什么。这是您必须向库的作者要求的明确答案。

我们可以推测是因为没有一种将整数转换为字符串的方法。也许假设以10为基数的表示形式不包含前导零将是一个合理的选择,但没有令人信服的理由为什么这必须是唯一的选择。

十六进制编码的字符串,科学计数法,数千个分隔符或任何其他可能的其他选项呢?

另一个可能的原因是整数键建议使用稀疏数组,因此可能不清楚您是要在输出中生成对象还是要生成数组。


一种可能的解决方案是构建一个助手,该助手通过通过std::map<std::string,TValue>运行键来将任何映射转换为std::to_string()

// 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;
}