C++ 使用nlohmann解析Json数据&数据对象建模

​ 援引百度百科:json是一种轻量级的数据交换格式。对于习惯了python语言的我来说,json可以和内置的dict(字典)数据类型完美衔接, 所以就想着能不能横向推广到C++。 在GitHub上一搜索,发现star最高的nlohmann;主要的用法工程的readme其实已经说的很清楚了。

​ 但是翻了很多博客,发现对于json 对象建模以及其相互转换的文档不多。此篇文章主要介绍读取json文件以及对象建模。希望对大家有所帮助!

一:将nlohmann库添加到自己的工程

​ 使用nlohmann,我们只需将json.hpp头文件添加到自己的代码中(这个超级Nice)

#include <json.hpp>

// 为了使用方便,可以让json命名空间内所有标识符在此文件中可见
using json = nlohmann::json;

二:简单json字符串序列化/反序列化

  1. 反序列化成json

    现有json字符串格式如下

    {
    	"pi":3.1415,
    	"happy":true
    }
    

    将其反序列化成json对象

    //方式1:在序列化后字符串后后添加 _json后缀
    json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
    
    //方式2:从原生字符串
    auto j2 = R"(
      {
        "happy": true,
        "pi": 3.141
      }
    )"_json;
    
    //方式3:显示的调用 json::parse
    auto j3 = json::parse(R"({"happy": true, "pi": 3.141})");
    
    //方式4:从json文件中读取
    std::ifstream ifs("test.json");
    json jf = json::parse(ifs);
    
  2. 序列化成json格式字符串

    // 显示的转换
    std::string s = j.dump();    // {"happy":true,"pi":3.141}
    
  3. 读取json文件

    std::ifstream ifs("test.json");
    json jf = json::parse(ifs);
    
  4. 保存成json文件

     jsonf jsonfile;
    
     jsonfile["happy"] = true;
     jsonfile["pi"] = 3.141;
     
     std::ofstream file("test.json");
     file << jsonfile;
    

三:较复杂的嵌套json字符串数据对象建模

现有json字符串格式如下:

{
	"teacher_name": "wangwu",
	"student_list": 
	[
		{
		"name": "zhangsan",
		"age": 16,
		"phone": "12345678"
		},
		{
		"name": "lisi",
		"age": 17,
		"phone": "123456"
		}
	]
}

对于较为复杂的嵌套json字符串,通用的做法是对其进行建模,对应到C++则是结构体/类

  1. json字符串分析

    直观的看的话, 此json字符串包含两种两大部分:teacher_name和student_list, 其中student_list是一个数组。student_list嵌套的内容包含name、age和phone3个字段

  2. 建模

    1. 最里层的表示学生对象的json字符串可转成对应的 student 类/结构体

      class student
      {
          public:	
              string name;
              int age;
              string phone;
      };
      
    2. 外层的表示班主任及学生列表的对象可转换成对应的***class_room***类/结构体, 其中学生列表可以用vector容器表示

      class class_room 
      {
          public:
              string teacher_name;
              std::vector<student> student_list;
      };
      
    3. 为了能够对这两个模型进行自由转换,需要对每个类/结构体分别提供两个函数

      // 对于student对象
      void from_json(const json& j, student& p)
      {
          j.at("name").get_to(p.name);
          j.at("age").get_to(p.age);
          j.at("phone").get_to(p.phone);
      }
      
      void to_json(json& j, const student& s)
      {
      	j = json{ { "name", s.name },{ "age",s.age },{ "phone", s.phone } };
      }
      
      
      //对于class_room对象
      void from_json(const json& j, class_room& p)
      {
          j.at("teacher_name").get_to(p.teacher_name);
      
          for (auto &student_t : j["student_list"])
          {
              student s;
              from_json(student_t, s);
              p.student_list.push_back(s);
          }
      }
      
      void to_json(json& j, const class_room& s)
      {
          j = json{ {"teacher_name", s.teacher_name } };
          for (auto & student_t : s.student_list)
          {
              json j_student;
              to_json(j_student, student_t);
              j["student_list"].push_back(j_student);
          }
      }
      

      当使用class_room字符串调用json的构造函数时,相应的to_json函数就会被调用,调用完成后对应的json对象就解析完成。反过来,如果调用***get***或者***get_to***时,from_json方法将会被调用

    4. 注意事项:

      1. 上面3步的都应包含在同一个namespace中,否则nlohmann库将不能正确的进行转换。代码结构示例如下
      namespace ns
      {
          class A
          {
          	// 一些结构体变量
          }
          void from_json(const json& j, A& a)
          {
          	// 转换的代码
          }
          void to_json(json& j, const A& a)
          {
          	// 转换的代码
          }
      }
      
      1. 需要用到这些转换的功能时,相应的头文件必须被包含,否则也不能转换成功
      2. 访问json的元素时,尽量使用 at() 方法而不要使用 ***operator[]***, 因为如果当有key不存在时,at() 方法会抛出异常而 operator[] 不会
  3. json字符串转换成数据对象

    ns::class_room cr;
    ns::from_json(commands, cr);
    
    //接下来就可以针对对象进行操作了
    std::cout << cr.student_list[0].age << std::endl;
    cr.student_list[0].age += 10;
    
  4. 数据对象转换

    json j_2;
    ns::class_room cr;
    ns::to_json(j_2, cr);
    

关注公众号【兰亭汇】即可获取完整代码~
公众号图片
感兴趣的同学可以看看。公众号会不定时分享工作生活中的所见所闻~

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用C++完成TCP数据传输,可以使用socket库。以下是一个简单的示例代码,演示如何使用JSON格式进行数据传输: ```C++ #include <iostream> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <nlohmann/json.hpp> using json = nlohmann::json; int main(int argc, char const *argv[]) { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { std::cerr << "Failed to create socket" << std::endl; return 1; } sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(12345); if (connect(sock, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) { std::cerr << "Failed to connect to server" << std::endl; return 1; } json j; j["name"] = "Alice"; j["age"] = 20; std::string message = j.dump(); if (send(sock, message.c_str(), message.size(), 0) == -1) { std::cerr << "Failed to send data" << std::endl; return 1; } char buffer[1024] = {0}; int received_size = recv(sock, buffer, sizeof(buffer), 0); if (received_size == -1) { std::cerr << "Failed to receive data" << std::endl; return 1; } json response = json::parse(buffer, buffer + received_size); std::cout << "Received response: " << response.dump() << std::endl; close(sock); return 0; } ``` 在这个示例中,我们使用nlohmann/json库来处理JSON数据。首先创建了一个JSON对象,将数据填入其中,并使用`dump()`方法将其转换为字符串。 然后,使用`socket()`函数创建一个套接字,并使用`connect()`函数连接到服务器。发送数据时,使用`send()`函数将JSON字符串发送给服务器。接收数据时,使用`recv()`函数接收服务器的响应,并将其解析JSON对象。 需要注意的是,在实际应用中,需要添加错误处理和异常情况的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_40603938

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值