nlohmann::json如何实现支持多键深层取值的通用get函数
实现方案
核心思路
基于C可变参数模板实现任意层数的嵌套JSON取值,逐层向下访问节点,兼容任意数量的键参数输入。以下分别提供C17(更简洁)和C++11兼容版本的实现。
C++17 折叠表达式实现(推荐)
直接利用C++17的折叠表达式语法简化逐层取值逻辑,无需递归:
#include <nlohmann/json.hpp> #include <string> #include <fstream> #include <iostream> #include <utility> using json = nlohmann::json; class My_config { public: My_config(const std::string config_path) { std::ifstream ifs(config_path); if (ifs.is_open()) { file_content = json::parse(ifs); ifs.close(); } } // 可变参数通用get函数 template<typename... Keys> json get(const std::string& first_key, Keys&&... rest_keys) { json current = file_content[first_key]; // 折叠表达式依次应用剩余所有键 ((current = current[std::forward<Keys>(rest_keys)]), ...); return current; } private: json file_content; }; int main() { auto my_conf = My_config("../test.json"); std::cout << "Get happy : " << my_conf.get("happy") << std::endl; // 两层嵌套取值 std::cout << "Get [answer][everything] : " << my_conf.get("answer", "everything") << std::endl; // 支持更多层,比如三层嵌套可直接写my_conf.get("a","b","c") return 0; }
C++11 兼容递归实现
如果使用C++11标准,可通过递归可变参数模板实现相同效果:
#include <nlohmann/json.hpp> #include <string> #include <fstream> #include <iostream> using json = nlohmann::json; class My_config { public: My_config(const std::string config_path) { std::ifstream ifs(config_path); if (ifs.is_open()) { file_content = json::parse(ifs); ifs.close(); } } // 单键取值(递归终止条件) json get(const std::string& key) { return file_content[key]; } // 多键递归取值 template<typename... RestKeys> json get(const std::string& first_key, RestKeys... rest_keys) { return get_impl(file_content[first_key], rest_keys...); } private: json file_content; // 递归终止:最后一层键 json get_impl(const json& current, const std::string& key) { return current[key]; } // 递归逐层访问 template<typename... RestKeys> json get_impl(const json& current, const std::string& key, RestKeys... rest_keys) { return get_impl(current[key], rest_keys...); } }; int main() { auto my_conf = My_config("../test.json"); std::cout << "Get happy : " << my_conf.get("happy") << std::endl; std::cout << "Get [answer][everything] : " << my_conf.get("answer", "everything") << std::endl; return 0; }
运行结果
测试用test.json的输出如下:
Get happy : true Get [answer][everything] : 42
可选优化点
- 异常处理:默认情况下如果路径中某层键不存在,nlohmann/json会抛出
nlohmann::json::out_of_range异常,可在get函数中添加contains判断,不存在时返回默认值或自定义异常。 - 数组支持:如果需要支持JSON数组的下标取值,可将参数类型调整为
std::variant<std::string, size_t>适配字符串键和整数索引的混合路径。
内容的提问来源于stack exchange,提问作者Furlings
相关产品推荐
相关产品推荐

