Bootstrap

c++开源项目nlohmann/json快速上手

一、nlohmann/json

1、简介

在这里插入图片描述

1、类似python调用json库一样, 非常的方便和直观。 绑定STL。
2、内存占用优化和运行速度并不是非常关心。

那里有无数的JSON库,每个库甚至都有其存在的理由。我们有这些设计目标:

直观的语法。 在 Python 等语言中,JSON 感觉就像是一流的数据类型。我们使用了现代 C++ 的所有运算符魔术来在您的代码中实现相同的感觉。看看下面的例子,你就会明白我的意思。

微不足道的整合。 我们的整个代码由一个头文件组成json.hpp。就是这样。没有库,没有子项目,没有依赖项,没有复杂的构建系统。该类是用 C++11 编写的。总而言之,一切都不需要调整编译器标志或项目设置。

非常全面的测试。 我们的课程经过大量单元测试,涵盖了100%的代码,包括所有异常行为。此外,我们使用Valgrind和Clang Sanitizers检查了没有内存泄漏。Google OSS-Fuzz还针对所有解析器 24/7 运行模糊测试,迄今为止有效执行了数十亿次测试。为了保持高质量,该项目遵循核心基础设施倡议 (CII) 最佳实践。

其他方面对我们来说并不那么重要:

内存效率。 每个 JSON 对象都有一个指针(联合的最大大小)和一个枚举元素(1 个字节)的开销。默认泛化使用以下 C++ 数据类型:std::string字符串、int64_t数字、对象、数组和uint64_t布尔值。但是,您可以根据需要对通用类进行模板化。doublestd::mapstd::vectorboolbasic_json

速度。 当然有更快的 JSON 库。但是,如果您的目标是通过添加带有单个标头的 JSON 支持来加速您的开发,那么这个库就是您要走的路。如果您知道如何使用std::vectoror std::map,那么您已经准备好了。

2. cmake环境搭建

# 下载json代码
include(FetchContent)
FetchContent_Declare(
    nlohmann_json
    GIT_REPOSITORY https://github.com/nlohmann/json
    GIT_TAG v3.11.3
    GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(nlohmann_json)
// 编译json代码,并链接到库
add_executable(json_guide main.cpp)
target_link_libraries(json_guide PRIVATE nlohmann_json::nlohmann_json)


二、 解析json文件 (反序列化)

1.1 从文件中读入json

#include <fstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

// ...

std::ifstream f("example.json");
json data = json::parse(f);

1.2 字符串读入 (序列化)

// Using (raw) string literals and json::parse
json ex1 = json::parse(R"(
  {
    "pi": 3.141,
    "happy": true
  }
)");

1.3 从json对象中解析数据

  • 解析普通数据
// strings
std::string s1 = "Hello, world!";
json js = s1;
auto s2 = js.template get<std::string>();
// NOT RECOMMENDED
std::string s3 = js;
std::string s4;
s4 = js;

// Booleans
bool b1 = true;
json jb = b1;
auto b2 = jb.template get<bool>();
// NOT RECOMMENDED
bool b3 = jb;
bool b4;
b4 = jb;

// numbers
int i = 42;
json jn = i;
auto f = jn.template get<double>();
// NOT RECOMMENDED
double f2 = jb;
double f3;
f3 = jb;

// etc.
  • 枚举类型解析
    该json库提供了一种特殊的直接从json文件中,解析出枚举类型值的方法。

  • 将json
// create a JSON value
json j = R"({"compact": true, "schema": 0})"_json;

// serialize to BSON
std::vector<std::uint8_t> v_bson = json::to_bson(j);

1.4 解析json对象的属性

假设有一个 json 对象:

j["list"] = { 1, 0, 2 };

// 1. at获取
float pi = j.at("pi");
for(int i=0; i<3; i++)
    std::cout << j.at("list").at(i) << std::endl;

json j;
j["name"] = p.name;
// 2. get获取
j["name"].get<std::string>(),

// 3. 判断j是否有这个属性
if (j.find("xxx") != j.end()) {
    cout << j.at("xxx");
    j["xxx"].get<std::string>();
}

// 4. 判断j是否有这个属性
  if (j_obj.contains("data")) {
    cout << j_obj.at("data") << endl;
    j_obj["data"] = "999999";
  } else {
    cout << "no had" << endl;
  }

// 5. 从json中读取数据
if (j_obj.contains("data")) {
    cout << "------------" << endl;
    cout << j_obj["data"].get<std::string>() << endl;
    cout << "------------" << endl;
  }

三. 导出都json文件

2.1 c++对象和Json字段映射

// create an empty structure (null)
json j;

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

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

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

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

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

// add an array that is stored as std::vector (using an initializer list)
j["list"] = { 1, 0, 2 };

// add another object (using an initializer list of pairs)
j["object"] = { {"currency", "USD"}, {"value", 42.99} };

2.2 导入到文件

// read a JSON file
std::ifstream i("file.json");
json j;
i >> j;

// write prettified JSON to another file
std::ofstream o("pretty.json");
o << std::setw(4) << j << std::endl;

2.3 导出到string

// explicit conversion to string
std::string s = j.dump();    // {"happy":true,"pi":3.141}

// serialization with pretty printing
// pass in the amount of spaces to indent
std::cout << j.dump(4) << std::endl;
// {
//     "happy": true,
//     "pi": 3.141
// }

四、常用API

  • accept, 查看是不是合法的json文本
    // an invalid JSON text
    auto invalid_text = R"(
    {
        "strings": ["extra", "comma", ]
    }
    )";

    std::cout << std::boolalpha
              << json::accept(valid_text) << ' '
  • json::array() 新建一个json数组
  • j.at()

demo 工程

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

#include <nlohmann/json.hpp>
using json = nlohmann::json;

void save_example_json_file(const std::string &filepath) {
  json j;
  j["name"] = "test";
}

json load_example(const std::string &filepath) {
  ifstream f(filepath.c_str());
  json data = json::parse(f);
  return std::move(data);
}

int main(int argc, char const *argv[]) {
  json j_obj =
      load_example("/Users/chendongsheng/github/algo/src/json/test.json");
  cout << j_obj.dump(4) << endl;

  auto i = j_obj.find("persion_list");
  if (i == j_obj.end()) {
    cout << "it's end" << endl;
  } else {
    cout << i.key() << endl;
    cout << i.value() << endl;
  }

  if (j_obj.contains("data")) {
    // cout << j_obj.at("data")  << endl;
    cout << "------------" << endl;
    cout << j_obj["data"].get<std::string>() << endl;
    cout << "------------" << endl;
    j_obj["data"] = "999999";
  } else {
    cout << "no had" << endl;
  }
  std::ofstream file("/Users/chendongsheng/github/algo/src/json/pretty.json");
  file << j_obj << std::endl;

  return 0;
}

在这里插入图片描述

;