nlohmann::json从入门到精通

打印 上一主题 下一主题

主题 1048|帖子 1048|积分 3144

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
nlohmann简介    

        nlohmann的劈头与发展    

        与其他c++ json库的比力    

        nlohmann的架构与计划理 

nlohmann在C++中的应用    

        nlohmann的安装与引用    

        根本语法    

        高级语法

一、nlohmann简介 
1、nlohmann的劈头与发展
nlohmann/json.hpp 的劈头可以追溯到其创建者 Niels Lohmann 的个人需求。 Niels Lohmann 在使用其他 C++ JSON 库时,发现这些库要么过于复杂, 要么性能不佳,要么使用起来不够直观。因此,他决定自己开发一个满意 这些需求的 JSON 库。经过一段时间的开发和优化,nlohmann/json.hpp  逐渐成为了一个功能全面、性能卓越的 JSON 库。它支持 C++11 及更高版本 的尺度,充分使用了现代 C++ 的特性,如范围 for循环、布局化绑定等, 使得操纵 JSON 数据变得更加简单和直观。随着其在 GitHub 上的开源 和发布,nlohmann/json.hpp 迅速得到了广泛的关注和认可。大量的用户 和贡献者参加了这个项目,为其提供了丰富的功能和稳固的性能。如今, nlohmann/json.hpp 已经成为 C++ 社区中非常受接待的 JSON 库之一。
2、与其他c++ json库的比力
与其他 C++ JSON 库相比,nlohmann/json.hpp 有以下显著上风: 易用性:nlohmann/json.hpp 提供了直观且易于使用的 API,使得开发者 可以或许快速地理解和使用它。与其他库相比,它减少了学习成本,提高了 开发效率。 高性能:在解析和生成 JSON 数据方面,nlohmann/json.hpp 体现出色。 它的性能优于很多其他 C++ JSON 库,使得在处理大量 JSON 数据时 更加高效。 单文件库:nlohmann/json.hpp 是一个单文件库,无需额外的链接或构建 步骤。这使得它非常轻易集成到任何 C++ 项目中,无论项目巨细如何。
3、nlohmann的架构与计划理 念
nlohmann/json.hpp 的架构和计划理念主要体如今以下几个方面: 简洁性:库的计划力求简洁明了,制止不须要的复杂性和冗余。这使得代码易于阅读和维护,同时也降低了堕落的可能性。 面向对象:库接纳了面向对象的计划思想,将 JSON 数据表现为对象或数组。这使得开发者可以或许以更直观的方式操纵 JSON 数据,提高了代码的可读性和可维护性。 灵活性:库提供了多种解析和生成 JSON 数据的方式,包括基于 SAX 和 DOM 的解析模式。这使得开发者可以或许根据自己的需求选择最符合的解析方式。 安全性:库在计划时充分思量了安全性因素,制止了潜伏的安全毛病和错误。它提供了严格的范例检查和错误处理机制,确保了在处理 JSON 数据时的安全性和可靠性。
SAX是一种基于事件的解析方式。解析器在读取JSON/XML文档时,每当碰到特定的元素(如开始标签、结束标签、字符数据等),就会触发相应的事件。开发者需要编写事件处理函数来相应这些事件。SAX解析器不需要将整个文档加载到内存中,因此它非常得当处理大型JSON/XML文档。  DOM是一种基于树的解析方式。解析器将整个JSON/XML文档加载到内存中,并构建出一个与文档布局对应的树形布局(DOM树)。开发者可以通过遍历DOM树来访问和操纵JSON/XML数据。由于DOM需要将整个文档加载到内存中,因此它更得当处理较小的JSON/XML文档
  1. //SAX解析
  2. struct MySax {
  3.     bool null() {
  4.         // 处理 null 值
  5.         return true;
  6.     }
  7.     bool boolean(bool val) {
  8.         // 处理 boolean 值
  9.         return true;
  10.     }
  11.     bool number_integer(json::number_integer_t val) {
  12.         // 处理整数
  13.         return true;
  14.     }
  15.     bool number_unsigned(json::number_unsigned_t val) {
  16.         // 处理无符号整数
  17.         return true;
  18.     }
  19.     bool number_float(double val, const std::string& /*unused*/) {
  20.         // 处理浮点数
  21.         return true;
  22.     }
  23.     bool string(const std::string& val) {
  24.         // 处理字符串
  25.         std::cout << current_key << ": " << val << std::endl;
  26.         return true;
  27.     }
  28.     bool start_object(size_t len) {
  29.         // 处理对象开始
  30.         return true;
  31.     }
  32.     bool key(const std::string& val) {
  33.         // 处理对象的键
  34.         current_key = val;
  35.         return true;
  36.     }
  37.     bool end_object() {
  38.         // 处理对象结束
  39.         return true;
  40.     }
  41.     bool start_array(size_t len) {
  42.         // 处理数组开始
  43.         std::cout<<"array start"<<std::endl;
  44.         return true;
  45.     }
  46.     bool end_array() {
  47.         // 处理数组结束
  48.         std::cout<<"array end"<<std::endl;
  49.         return true;
  50.     }
  51.     bool parse_error(size_t len, std::string str, exception e)
  52.     {
  53.         return true;
  54.     }
  55.     bool binary(const std::vector<std::uint8_t>& data) {
  56.         // 处理二进制数据
  57.         // 例如,可以将数据转换为字符串或进行其他操作
  58.         return true;
  59.     }
  60. private:
  61.     std::string current_key; // 存储当前处理的键
  62.     std::list<std::string> m_array;
  63. };
  64. #include "nlohmann/json.hpp"
  65. #include <iostream>
  66. #include <fstream>
  67. #include <sstream>
  68. void main()
  69. {
  70.     std::string jsonStr = R"(
  71.            {
  72.                "name": "John",
  73.                "age": 30,
  74.                "city": "New York",
  75.                "skills": ["C++", "Java", "Python"]
  76.            }
  77.        )";
  78.     std::istringstream iss(jsonStr);
  79.     MySax sax_handler;
  80.     bool success = nlohmann::json::sax_parse(iss, &sax_handler);
  81.     if (!success) {
  82.        std::cerr << "SAX parsing failed!" << std::endl;
  83.     } else {
  84.        std::cout << "SAX parsing successful!" << std::endl;
  85.     }
  86. }
复制代码
  1. //DOM解析
  2. std::string jsonStr = R"(
  3.            {
  4.                "name": "John",
  5.                "age": 30,
  6.                "city": "New York",
  7.                "skills": ["C++", "Java", "Python"]
  8.            }
  9.        )";
  10. nlohmann::json j = nlohmann::json::parse(jsonStr);
复制代码
  1. //类型检查
  2. nlohmann::json j = nlohmann::json::parse(jsonStr);
  3.     if(j.contains("age") && j.at("age").is_number_integer()){
  4.         int _age = j.at("age").get<int>();
  5.         cout<<"age:"<<_age<<endl;
  6.     }
  7. //错误处理
  8.     try {
  9.         int _age = j.at("age").get<bool>();
  10.         cout<<"age1:"<<_age<<endl;
  11.     } catch (json::exception& e) {
  12.         cout<<e.what()<<endl;
  13.     }
复制代码
二、nlohmann在C++中的应用
1、nlohmann的安装与引用
安装nlohmann/json.hpp非常简单,只需将json.hpp头文件复制到项目的适当位置即可。在C++源文件中,通过包含#include "nlohmann/json.hpp"来引用该库。
2、根本语法
  1. //创建JSON对象
  2. //可以使用nlohmann::json类来创建JSON对象,通过键值对的方式添加数据。
  3. #include "nlohmann/json.hpp"  
  4.   
  5. int main() {  
  6.     nlohmann::json j;  
  7.     j["name"] = "John Doe";  
  8.     j["age"] = 30;  
  9.     j["is_student"] = false;  
  10.     return 0;  
  11. }
  12. //解析JSON字符串
  13. //nlohmann::json类还提供了从JSON字符串解析数据的功能。
  14. int main() {  
  15.     std::string json_str = R"({"name": "Jane Smith", "age": 25, "is_student": true})";  
  16.     nlohmann::json j = nlohmann::json::parse(json_str);  
  17.   
  18.     std::cout << "Name: " << j["name"] << std::endl;  
  19.     std::cout << "Age: " << j["age"] << std::endl;  
  20.     std::cout << "Is Student: " << j["is_student"].get<bool>() << std::endl;  
  21.     return 0;  
  22. }
  23. //生成JSON字符串
  24. //可以使用dump()方法将nlohmann::json对象转换为JSON字符串。
  25. int main() {  
  26.     nlohmann::json j;  
  27.     j["name"] = "Alice";  
  28.     j["hobbies"] = nlohmann::json::array({ "reading", "painting", "swimming" });  
  29.   
  30.     std::string json_str = j.dump(4); // 4表示缩进空格数  
  31.     std::cout << json_str << std::endl;  
  32.   
  33.     return 0;  
  34. }
复制代码
3、高级语法
  1. //遍历JSON对象
  2. nlohmann::json j = {  
  3.         {"name", "Bob"},  
  4.         {"age", 28},  
  5.         {"address", {  
  6.             {"street", "123 Main St"},  
  7.             {"city", "New York"},  
  8.             {"state", "NY"}  
  9.         }}  
  10. //结构化绑定
  11.     for (const auto& [key, value] : j.items()) {  
  12.         std::cout << "Key: " << key << ", Value: " << value << std::endl;  
  13.     }  
  14. //迭代器遍历
  15.     for (auto it = j.begin(); it != j.end(); ++it) {
  16.         std::cout << "Key: " << it.key() << ", Value: " << it.value() << std::endl;
  17.     }
  18. //遍历值
  19.     for (const auto& value : j) {
  20.         std::cout << "value: " << value<<std::endl;
  21.     }   
  22. //    for(const auto& [key, value] : j.items()) {
  23. //        std::cout << "Key: " << key << ", Value: " << value << std::endl;
  24. //        if (value.is_object()) {
  25. //            for (const auto& [uuid, board] : value.items()) {
  26. //                std::cout << "  Board UUID: " << uuid << std::endl;
  27. //                for (const auto& [board_key, board_value] : board.items()) {
  28. //                    std::cout << "    " << board_key << ": " << board_value << std::endl;
  29. //                }
  30. //            }
  31. //        }
  32. //    }
  33. //    for (const auto& item : j.items()) {
  34. //        std::cout << "Key: " << item.key() << ", Value: " << item.value() << std::endl;
  35. //        // 如果value是另一个json对象,递归遍历它
  36. //        if (item.value().is_object()) {
  37. //            for (const auto& inner_item : item.value().items()) {
  38. //                std::cout << "  Inner Key: " << inner_item.key() << ", Inner Value: " << inner_item.value() << std::endl;
  39. //            }
  40. //        }
  41. //    }
  42. //JSON数组操作
  43. //nlohmann::json还支持JSON数组的操作,可以添加、删除和修改数组元素。
  44. int main() {  
  45.     nlohmann::json arr = nlohmann::json::array();  
  46.     arr.push_back("Apple");  
  47.     arr.push_back("Banana");  
  48.     arr.push_back("Cherry");  
  49.   
  50.     arr[1] = "Blueberry"; // 修改数组中的元素  
  51.     arr.pop_back(); // 删除数组中的最后一个元素  
  52.     for (const auto& value : arr) {  
  53.         std::cout << value << std::endl;  
  54.     }  
  55.     return 0;  
  56. }
复制代码
  1. 序列化和反序列化
  2. #include "nlohmann/json.hpp"
  3. class TestA
  4. {
  5. public:
  6.     TestA(){}
  7.     TestA(int v1, string v2):i(v1),s(v2) {}
  8.     int i;
  9.     string s;
  10. void to_json(nlohmann::json& j) const {
  11.              j = nlohmann::json{{"i", i}, {"s", s}};
  12.          }
  13. void from_json(const nlohmann::json& j) {
  14.          i = j["i"];
  15.          s = j["s"];
  16.      }
  17. //或者使用下面的宏来序列化和反序列化
  18. //NLOHMANN_DEFINE_TYPE_INTRUSIVE(TestA, i, s)
  19. };
  20. void main()
  21. {
  22.     std::string json_str = R"({
  23.         "i": 1,
  24.         "s": "str"
  25.     })";
  26.     json j1 = json::parse(json_str);
  27.     TestA B;
  28.     //反序列化
  29.     B.from_json(j1);
  30.     cout<<B.i<<B.s<<endl;
  31. }
复制代码
注意:
j.at("name").get_to(p.name) 和 p.name = j["name"] 都是将 JSON 对象中的指定字段值赋给布局体 xxx 中的成员变量 name。 然而,它们之间存在一些区别: 异常处理:j.at("name").get_to(p.name) 使用 at() 函数来获取指定字段的值,并将其赋给 p.name。如果 JSON 对象中不存在指定的字段,大概字段的值范例与 p.name 的范例不匹配,将抛出 json:ut_of_range 或 json::type_error 异常。这使得您可以在出现错误时进行适当的异常处理。 容错性:p.name = j["name"] 使用索引运算符 [] 来获取指定字段的值,并将其赋给 p.name。如果 JSON 对象中不存在指定的字段,大概字段的值范例与 p.name 的范例不匹配,将引发未定义的举动。这意味着您需要确保 JSON 对象中存在指定的字段,并且字段的值范例与 p.name 的范例匹配,否则可能导致步伐瓦解或产生不正确的效果。因此,如果您渴望在 JSON 对象中不存在指定字段或字段范例不匹配时进行异常处理,并且更加安全和可靠,请使用 j.at("name").get_to(p.name)。如果您确定 JSON 对象中存在指定字段,并且字段的值范例与 p.name 的范例匹配,可以使用 p.name = j["name"] 来简化代码。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表