如何用nlohmann/json序列化/反序列化std::map<int, MyObject>?仅转int键为string
用nlohmann/json序列化std::map<int, MyObject>的正确姿势
嘿,这个问题我之前也踩过坑!其实你完全不用手动实现std::map<int, MyObject>的to_json和from_json函数——nlohmann/json库原生就支持std::map的序列化/反序列化,只要满足两个简单条件:
- 你的
MyObject类型已经正确实现了对应的序列化函数(你已经写好了,重点是要把这些函数放在和MyObject同一个命名空间里,这样库才能通过ADL(参数依赖查找)找到它们) - map的键类型(这里是
int)能被转换为std::string——而int是库默认支持的类型,会自动用std::to_string转成字符串键,根本不用你额外写代码!
直接能用的示例代码
先给你一段可以直接跑的完整代码,验证一下:
#include <nlohmann/json.hpp> #include <map> #include <string> #include <iostream> using nlohmann::json; namespace ns { // 你的自定义对象 struct MyObject { std::string name; std::string address; int age; }; // 序列化函数,必须和MyObject同命名空间! 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 int main() { // 构建测试用的map std::map<int, ns::MyObject> user_map; user_map[1] = {"Alice", "123 Main St", 30}; user_map[2] = {"Bob", "456 Oak Ave", 25}; // 直接序列化,库会自动处理int键转string和MyObject的序列化 json j = user_map; // 格式化输出JSON,你会看到键是"1"、"2"这样的字符串 std::cout << j.dump(4) << std::endl; // 反序列化也一样简单 std::map<int, ns::MyObject> restored_map = j.get<std::map<int, ns::MyObject>>(); return 0; }
运行这段代码后,输出的JSON会是这样的:
{ "1": { "name": "Alice", "address": "123 Main St", "age": 30 }, "2": { "name": "Bob", "address": "456 Oak Ave", "age": 25 } }
如果你想自定义int键的格式
要是你不想用默认的数字字符串(比如想给键加个前缀,变成"user_1"、"user_2"),那可以通过特化库的key_access结构体来实现自定义转换:
#include <nlohmann/json.hpp> #include <string> namespace nlohmann::detail { // 特化int类型的键访问逻辑 template <> struct key_access<int> { // 序列化时把int转成自定义格式的字符串 static void to_json(json& j, const int& key) { j = "user_" + std::to_string(key); } // 反序列化时从自定义字符串还原int static void from_json(const json& j, int& key) { std::string key_str = j.get<std::string>(); // 去掉前缀"user_",还原数字 if (key_str.starts_with("user_")) { key = std::stoi(key_str.substr(5)); } else { throw json::parse_error(0, "Invalid key format: expected 'user_*'"); } } }; } // namespace nlohmann::detail
加了这段代码后,序列化出来的键就会变成"user_1"、"user_2",反序列化时也能正确把这些字符串转回到int键。
最关键的注意事项
- 一定要把
MyObject的to_json和from_json函数放在和MyObject同一个命名空间里,不然库找不到这些函数,会导致序列化失败。 - 只要用默认的int转string,完全不需要额外写任何代码,库会自动处理map的序列化/反序列化。
- 只有当你需要自定义键的格式时,才需要特化
key_access或者写自定义转换逻辑。
内容的提问来源于stack exchange,提问作者Poperton
相关产品推荐
相关产品推荐

