nlohmann/json简介及使用
nlohmann/json是GitHub上开源的一个现代C++ JSON,源码地址:https://github.com/nlohmann/json ,最新发布版本为v3.12.0,License为MIT。
注意事项:
(1).json.hpp文件存在两处:两处的json.hpp功能相同
single_include/nlohmann目录下:所有功能全部在json.hpp文件中
include/nlohmann目录下:此json.hpp内会include其它头文件
(2).该库仅支持UTF-8,当你在库中存储不同编码的字符串时,调用dump()可能会引发异常,除非使用 json::error_handler_t::replace或json::error_handler_t::ignore作为错误处理程序。
(3).该库支持BSON(二进制JSON)、CBOR(简洁二进制对象表示)、MessagePack、UBJSON(通用二进制JSON规范)和BJData(二进制JData),以便高效地将JSON值编码为字节向量并对其进行解码。它们默认存储为std::vector<std::uint8_t>,以便在库外部处理。
(4).该库默认不支持注释。但是,你可以在解析函数中将设置参数ignore_comments设置为true,以忽略//或/* */注释。这样,注释将被视为空格。
(5).尾随逗号(trailing commas):JSON规范不允许在数组和对象中使用尾随逗号,因此该库默认将其视为解析错误。与注释类似,你可以在解析函数中将参数 ignore_trailing_commas设置为true,以忽略数组和对象中的尾随逗号。
(6).对象键的顺序:默认情况下,该库不保留对象元素的插入顺序。这符合标准,因为JSON标准将对象定义为"零个或多个键/值对的无序集合"。如果你确实希望保留插入顺序,可以尝试nlohmann::ordered_json类型。或者,你可以使用更复杂的有序映射,例如tsl::ordered_map(集成)或nlohmann::fifo_map(集成)。
生成json文件的测试代码如下:
int dump()
{auto numbers = R"({"numbers": [1, 2, 3]})";if (!json::accept(numbers)) {std::cerr << "Error: invalid json: " << numbers << std::endl;return -1;}json j_numbers = json::parse(numbers);auto city = R"({"city":"天津"})";if (!json::accept(city)) {std::cerr << "Error: invalid json: " << city << std::endl;return -1;}json j_city = json::parse(city);json merged{};merged.update(j_numbers);;merged.update(j_city);auto csdn = R"({"csdn": {"addr": "https://blog.csdn.net/fengbingchun", "visits": 14000000, "fan": 14000}})";if (!json::accept(csdn)) {std::cerr << "Error: invalid json: " << csdn << std::endl;return -1;}json j_csdn = json::parse(csdn);merged.merge_patch(j_csdn);merged["github"] = { {"addr","https://github.com/fengbingchun"}, {"stars",1400} };json j_hobbies = json::parse(R"({"hobbies": ["swimming", "table tennis"]})");merged.merge_patch(j_hobbies);auto j_fruits = R"({"fruits": ["peaches", "bananas", "melons"]})"_json;merged.merge_patch(j_fruits);std::ofstream out_file(file_name1);if (!out_file.is_open()) {std::cerr << "Error: failed to open json file: " << file_name1 << std::endl;return -1;}out_file << merged.dump(4);return 0;
}
生成的test.json内容如下:
注:当写入的json文件中包含中文字符时,需要:将.cpp文件格式调整为UTF-8 BOM、在.cpp中添加:#pragma execution_character_set("utf-8")
解析此json文件的测试代码如下:
int parse()
{SetConsoleOutputCP(CP_UTF8); // Chinese output is garbledstd::ifstream in_file(file_name1);if (!in_file.is_open()) {std::cerr << "Error: failed to open json file: " << file_name1 << std::endl;return -1;}json data = json::parse(in_file); auto city = data["city"];std::cout << "city:" << city << std::endl;auto csdn = data["csdn"];std::cout << "csdn: addr: " << csdn["addr"] << ", fan: " << csdn["fan"] << ", visits: " << data["csdn"]["visits"] << std::endl;auto github = data["github"];std::cout << "github: addr:" << github["addr"] << ", stars:" << github["stars"] << std::endl;std::cout << "fruits: ";auto fruits = data["fruits"]; // std::vector<string>for (const auto& fruit : fruits) {std::cout << fruit << ",";}std::cout << std::endl;if (data.contains("hobbies")) { // field may not existstd::cout << "hobbies: ";for (const auto& hobby : data["hobbies"]) {std::cout << hobby << ",";}std::cout << std::endl;}std::cout << "numbers: ";for (const auto& number : data["numbers"]) { // std::vector<int>std::cout << number << ",";}std::cout << std::endl;return 0;
}
运行以上代码,执行结果如下图所示:
注:当解析含有中文字符内容的json文件,并将结果正常显示到控制台时,需设置:SetConsoleOutputCP(CP_UTF8)
生成二进制json文件(BSON)的测试代码如下:
int dump_bson() // binary formats:BSON
{std::ifstream in_file(file_name1);if (!in_file.is_open()) {std::cerr << "Error: failed to open json file: " << file_name1 << std::endl;return -1;}json data = json::parse(in_file);std::vector<std::uint8_t> bson_data{};try {bson_data = json::to_bson(data);} catch (const json::type_error& e) {std::cerr << "Error: to_bson: " << e.what() << std::endl;return -1;}std::ofstream out_file(file_name2, std::ios::binary);if (!out_file.is_open()) {std::cerr << "Error: failed to open bson file: " << file_name2 << std::endl;return -1;}out_file.write(reinterpret_cast<const char*>(bson_data.data()), bson_data.size());return 0;
}
解析二进制json文件(BSON)的测试代码如下:
int parse_bson()
{std::ifstream in_file(file_name2, std::ios::binary);if (!in_file.is_open()) {std::cerr << "Error: failed to open bson file: " << file_name2 << std::endl;return -1;}auto j = json::from_bson(in_file);if (j.empty()) {std::cerr << "Error: failed to load bson" << std::endl;return -1;}if (!j.is_object()) {std::cerr << "Error: top-level elements are not objects" << std::endl;return -1;}if (!j.contains("city")) {std::cerr << "Error: missing field: city" << std::endl;return -1;}if (!j["city"].is_string()) {std::cerr << "Error: wrong field type" << std::endl;return -1;}auto csdn = j["csdn"];std::cout << "csdn: addr: " << csdn["addr"] << ", fan: " << csdn["fan"] << ", visits: " << j["csdn"]["visits"] << std::endl;auto github = j["github"];std::cout << "github: addr:" << github["addr"] << ", stars:" << github["stars"] << std::endl;return 0;
}
执行以上代码,执行结果如下图所示:
GitHub:https://github.com/fengbingchun/Messy_Test