nlohmann json的用法
nlohmann/json
是一个强大且易用的 C++ 库,用于处理 JSON 数据。它支持 JSON 格式与 C++ 数据结构之间无缝转换。
用法
github地址nlohmann/json: JSON for Modern C++ (github.com)
下载 https://github.com/nlohmann/json/tree/develop/include 下的nlohmann 目录,将其放到你项目的include目录下,在你需要使用的代码中 #include “nlohmann/json.hpp”
即可。
示例代码
# 目录结构
--nlohmann_json
----include/
------nlohmann/
--------json.hpp
--------other_files...
----build/
------test.json
------test0.json
------test1.json
----CMakeLists.txt
----nlohmann.json
----test_json.cpp
用法都放在下面的代码里。
#include <iostream>
#include <fstream>
#include <deque>
#include <set>
#include "nlohmann/json.hpp"
using njson = nlohmann::json; // using作用是为nlohmann::json类型创建别名
using ordered_njson = nlohmann::ordered_json;
/*默认情况下,nlohmann::json 使用 std::map 存储对象字段,
std::map 会按照键的字母顺序排序。如果不想对字段名进行排序,
可以改用 nlohmann::json 提供的 ordered_json 类型,
内部使用 std::unordered_map 来保持字段插入的顺序。
ordered_json的dump()函数,不会调整字段的顺序;
json的dump()函数,会按照字母顺序调整字段的顺序;
*/
namespace ns
{
struct guy{
int age;
std::string name;
// std::array<int, 5> array;
int array[5];
};
}
namespace ns2
{
struct guy2{
int age;
std::string name;
};
void to_json(njson& j, const guy2& g)
{
j = njson{{"age", g.age}, {"name", g.name}};
}
void from_json(const njson& j, guy2& g)
{
j.at("age").get_to(g.age);
j.at("name").get_to(g.name);
}
// to_json 和 from_json 在nlohmann::json中就定义了,这里相当于根据实际数据结构重载了一下
// 这里应该使用at(), 当读取不存在的字段时,它会抛出错误
}
using namespace std;
int main()
{
njson j;
j["username"] = "admin";
j["password"] = "admin123";
j["age"] = 24;
j["balance"] = 1009999.99;
j["married"] = false;
j["nothing"] = NULL; //nullptr
j["list"] = {0, 1, 2, 3};
j["object"] = {{"currency", "RMB"}, {"weight", 75}};
j["answer"]["number"] = 42;
j["answer"]["color"] = "black";
//j.at("") == j[""] 使用at(), 当读取不存在的字段时,会抛出错误
// std::string name_val = "val"; // name_val的值是一个变量
// j[val] = 1; // 若val变量的值对应的字段存在,则更新对应值,反之创建这个字段,写入值;
// j.at(val) = 1; 就不行,若该字段不存在,会报错std::out_of_range, 它是只读操作,不能用来赋值;
#if 0
// 新建nlohmann::json对象, 输出json信息
ofstream put_file("test.json");
// put_file << j << endl;
put_file << j.dump(4) << endl;
// cout << j.dump(4) << endl;
#endif
#if 0
// 从nlohmann::json中获取相关json元素的值
float balance = j.at("balance");
float balance2 = (&j)->at("balance");
float balance3 = j["balance"];
cout << balance << " " << balance2 << " " << balance3 << endl;
string username = j.at("username");
cout << username << endl;
for (const auto ele : j.at("list"))
{
cout << ele << " ";
}
cout << endl;
for (int i = 0; i < 4; i ++)
{
cout << j.at("list").at(i) << " ";
}
cout << endl;
cout << j.at("object").at("weight") << endl;
#endif
#if 0
// string的反序列化,字符串转成nlohmann::json对象
njson j2 = "{\"married\":true, \"age\":24}"_json;
cout << j2.dump(4) << endl;
auto j3 = R"({"married":true, "age":24})"_json;
cout << j3.dump(4) << endl;
// or
string str = "{\"married\":false, \"age\":18}";
auto j4 = njson::parse(str.c_str());
cout << j4.dump() << endl;
// string的序列化,nlohmann::json对象转成字符串
string str2 = j4.dump();
cout << str2 << endl;
string s1 = "Hello, World";
njson js1 = s1;
// 推荐
auto s2 = js1.get<std::string>();
// 不推荐
// string s3 = js1;
cout << js1.dump() << endl;
cout << s2 << endl;
#endif
#if 0
//文件操作
ifstream get_file("../nlohmann.json");
if (!get_file.is_open())
{
cerr << "failed to op json file !" << endl;
return -1;
}
stringstream buffer;
buffer << get_file.rdbuf();
string json_str = buffer.str();
njson j5 = njson::parse(json_str.c_str());
j5.at("married") = true;
cout << j5.dump(4) << endl;
ofstream put_file0("test0.json");
put_file0 << j5.dump(4) << endl;
ordered_njson j6 = ordered_njson::parse(json_str.c_str());
j6.at("married") = true;
cout << j6.dump(4) << endl;
ofstream put_file1("test1.json");
put_file1 << j6.dump(4) << endl;
// or
// ifstream get_file2("../nlohmann.json");
// njson j7;
// get_file2 >> j7;
// cout << j7.at("age") <<endl;
#endif
#if 0
// 任意类型转换
ns::guy boy{24, "Rekko", {6,5,4,3,2}};
// or
// ns::guy boy = {24, "Rekko", {6,5,4,3,2}};
njson j8;
// the wrong usage:
// j8.at("age") = boy.age;
// j8.at("name") = boy.name;
// j8.at("array") = boy.array;
j8["age"] = boy.age;
j8["name"] = boy.name;
j8["array"] = boy.array;
cout << j8.dump(4) <<endl;
ns::guy girl {
j8["age"].get<int>(),
j8["name"].get<std::string>(),
// j8["array"].get<std::array<int, 5>>(),
} ;
auto json_array = j8["array"];
if (json_array.size() == 5)
{
for (size_t i = 0; i < 5; i++)
{
girl.array[i] = json_array[i].get<int>();
}
}
else
{
cerr << "json array size is not right" <<endl;
}
cout << girl.age << " " << girl.name << endl;
for (auto i : girl.array)
{
cout << i << " ";
}
cout << endl;
#endif
#if 0
// 快速转换
ns2::guy2 man = {30, "Alen"};
njson j9 = man;
cout << j9.dump() << endl;
auto man2 = j9.get<ns2::guy2>();
cout << man2.age << " " << man2.name << endl;
assert(j9 == man2);
#endif
#if 0
// 转换到二进制
// json虽很常用,但它是非紧凑格式,不利于网络传输,或写入文件
// nlohmann库 支持很多种二进制格式,包括了bson, cbor, messagepack, ubjson, bjdata
njson jb = R"({"city": "shanghai", "school": "tongji"})"_json;
// json to bson
std::vector<std::uint8_t> b_bson = njson::to_bson(jb);
// bson to json
njson j_from_bson = njson::from_bson(b_bson);
// json to cbor
std::vector<std::uint8_t> b_cbor = njson::to_cbor(jb);
// cbor to json
njson j_from_cbor = njson::from_cbor(b_cbor);
// json to messagepack
std::vector<std::uint8_t> b_msgpack = njson::to_msgpack(jb);
// messagepack to json
njson j_from_b_msgpack = njson::from_msgpack(b_msgpack);
// json to ubjson
std::vector<std::uint8_t> b_ubjson = njson::to_ubjson(jb);
// ubjson to json
njson j_from_ubjson = njson::from_ubjson(b_ubjson);
// json to bjdata
std::vector<std::uint8_t> b_bjdata = njson::to_bjdata(jb);
// bjdata to json
njson j_from_bjdata = njson::from_bjdata(b_bjdata);
cout << jb.dump() << endl;
cout << j_from_bson.dump() << endl;
cout << j_from_cbor.dump() << endl;
cout << j_from_b_msgpack.dump() << endl;
cout << j_from_ubjson.dump() << endl;
cout << j_from_bjdata.dump() << endl;
ofstream out_bson("bson.bin", std::ios::out | std::ios::binary);
out_bson.write(reinterpret_cast<const char*>(b_bson.data()), b_bson.size() * sizeof(uint8_t));
out_bson.close();
ifstream in_bson("bson.bin", std::ios::in | std::ios::binary);
std::vector<uint8_t> b_buffer((std::istreambuf_iterator<char>(in_bson)), std::istreambuf_iterator<char>());
in_bson.close();
njson j_from_bson_file = njson::from_bson(b_buffer);
cout << j_from_bson_file.dump(4) << endl;
#endif
#if 0
/*
nlohmann 库支持从 STL 的任意序列容器初始化获得 json 对象(std::array, std::vector, std::deque, std::forward_list, std::list),
它们的值可以被用来构造 json 的值。
*/
/*
std::set, std::multiset, std::unordered_set, std::unordered_multiset关联容器也具有同样的用法,
并且也会保存其内在的顺序。
*/
/*
另外像std::map, std::multimap, std::unordered_map, std::unordered_multimap,nlohmann 也是支持的,
但是需要注意的是其中的 Key 被构造为 std::string 保存。
*/
std::vector<int> d_vector {6, 5, 4, 3, 2, 1};
njson j_vector(d_vector);
cout << j_vector.dump(4) << endl;
std::deque<double> d_deque {6.01, 5.02, 4.03};
njson j_deque(d_deque);
cout << j_deque.dump(4) << endl;
std::array<int, 3> d_array {0, 1, 2};
njson j_array(d_array);
cout << j_array.dump(4) << endl;
std::set<std::string> d_set {"one", "two", "three"};
njson j_set(d_set);
cout << j_set.dump(4) << endl;
std::map<std::string, int> d_map {{"age", 24}, {"weight", 75}};
njson j_map(d_map);
cout << j_map.dump(4) << endl;
#endif
#if 1
// nlohmann::json::array() 是一个静态方法,
// 用于创建一个 JSON 类型的空数组或初始化为指定值的数组。
njson j_array = njson::array();
cout << j_array.dump() << endl;
// []
njson j_array2 = njson::array({1, 2.01, "Rekko", true, {0, 1}});
cout << j_array2.dump() << endl;
// [1,2.01,"Rekko",true,[0,1]]
int age = 24;
int weight = 75;
int height = 175;
njson j_array3 = njson::array();
for (int i = 0; i < 3; i++)
{
njson j;
j["age"] = age++;
j["weight"] = weight++;
j["height"] = height++;
j_array3.push_back(j);
}
cout << j_array3.dump(4) << endl;
njson j_array4;
j_array4["changes"] = j_array3;
cout << j_array4.dump(4) << endl;
#endif
return 0;
}
参考文章:【C++ JSON 开源库】nlohmann入门使用总结 - fengMisaka - 博客园 (cnblogs.com)