消息序列化工具-为现代C++设计的jsoncpp介绍与使用技巧

2023-05-16

概述

JSON 的全称为:JavaScript Object Notation,顾名思义,JSON 是用于标记 Javascript 对象的,JSON 官方的解释为:JSON 是一种轻量级的数据传输格式。

本文并不详细介绍 JSON 本身的细节,旨在讨论如何使用 C++ 语言来处理 JSON。关于 JSON 更具体的信息,可参见 JSON 官网:http://www.json.org。

本文选择处理 JSON的 C++ 库

本文选择一个开源的 jsoncpp 来解析 JSON。jsoncpp 是比较出名的 C++ JSON 解析库。在 JSON 官网也是首推的。

项目地址

https://github.com/nlohmann/json.git

jsoncpp设计目标:

  • 直观的语法。在Python等语言中,JSON感觉像是第一类数据类型。该项目用了现代c++的所有运算符魔法来在代码中实现同样的感觉。

  • 化繁为简。整个代码由一个头文件json.hpp组成。没有库,没有子项目,没有依赖关系,没有复杂的构建系统。这个类是用普通c++ 11编写的。总而言之,一切都不需要调整编译器标志或项目设置。

  • 严格的测试。代码经过了大量的单元测试,覆盖了100%的代码,包括所有异常行为。此外,检查了Valgrind和Clang sanitizer,没有内存泄漏。谷歌OSS-Fuzz还对所有解析器全天候运行fuzz测试,到目前为止有效地执行了数十亿次测试。为了保持高质量,该项目遵循核心基础设施倡议(CII)的最佳实践。

clone

git clone https://github.com/nlohmann/json.git

或者克隆包含最近一次commit的分支

git clone https://github.com/nlohmann/json.git --depth=1

使用方法

  • 获取头文件

    cp json/single_include/nlohmann/json.hpp json.hpp
    
  • 在源文件中包含头文件

    #include "json.hpp"
    
  • 为便于使用,定义别名

    using Json = nlohmann::json;
    
  • 直接使用定义后的别名类和方法 Json and Json::parse directly

示例

使用起来简单方便,可以直接像C++的容器一样使用。
参考代码如下:

   //#define LOGI printf
   #define LOGI(...) \
      do { printf("%s:%3d ", __FILE__, __LINE__); printf(__VA_ARGS__); printf("\n"); } while (0)

   // create an empty structure (null)
   Json jo;

   // add a number that is stored as double (note the implicit conversion of jo to an object)
   jo["pi"] = 3.141;

   // add a Boolean that is stored as bool
   jo["happy"] = true;

   // add a string that is stored as std::string
   jo["name"] = "Niels";

   // add another null object by passing nullptr
   jo["nothing"] = nullptr;

   // add an object inside the object
   jo["answer"]["everything"] = 42;

   // add an array that is stored as std::vector (using an initializer list)
   jo["list"] = { 1, 0, 2 };
   std::vector<int> vect{3, 4, 5};
   jo["list2"] = vect;

   // add another object (using an initializer list of pairs)
   jo["object1"] = Json::array({ {"currency", "USD"}, {"value", 42.99} });
   jo["object2"] = { {"currency", "USD"}, {"value", 42.99} };

   // explicit conversion to string
   std::string str = jo.dump();
   LOGI("jo dump string: %s", str.c_str());

   // serialization with pretty printing
   // pass in the amount of spaces to indent
   LOGI("jo dump: %s", jo.dump(2).c_str());

   // instead, you could also write (which looks very similar to the JSON above)
   Json jo1 = {
       {"pi", 3.141},
       {"happy", true},
       {"name", "Niels"},
       {"nothing", nullptr},
       {"answer", {
                      {"everything", 42}
                  }},
       {"list", {1, 0, 2}},
       {"object", {
                      {"currency", "USD"},
                      {"value", 42.99}
                  }}
   };
   LOGI("jo1 dump: %s", jo1.dump(2).c_str());

   // parse explicitly
   Json jo2 = Json::parse(R"({"happy": true, "pi": 3.141})");
   LOGI("jo2 dump: %s", jo2.dump(2).c_str());

   Json jo3 = Json::parse(jo1.dump());
   if (jo3.contains("hello")) {
       std::string hello = jo3["hello"];
       // std::string hello = jo3.at("hello");
       LOGI("hello: %s", hello.c_str());
   } else {
       LOGI("not contains hello");
   }

   float pi = jo3["pi"];
   bool happy = jo3["happy"];
   std::string name = jo3["name"];
   int value = jo3["answer"]["everything"];
   std::list<int> ls = jo3["list"];

   LOGI("pi: %g", pi);
   LOGI("happy: %s", happy ? "true" : "false");
   LOGI("name: %s", name.c_str());
   LOGI("value: %d", value);
   for (auto &i : ls) {
       LOGI("list: %d", i);
   }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

消息序列化工具-为现代C++设计的jsoncpp介绍与使用技巧 的相关文章

随机推荐