irpas技术客

【C++】 nlohmann json_Dovake

网络投稿 1167

nlohman json: nlohmann json github

1. nlohman json 设计目标 直观的语法: 在如Python等编程语言中,JSON 感觉如同一种数据类型。我们运用现代 C++ 的语法特性使得在编码中有同样的感觉。容易集成: 所有的相关代码都包含在一个简单的json.hpp头文件中,没有其他的库文件,子项目,其他依赖以及复杂的编译系统。严格的测试。代码经过严格的单元测试和100%的代码覆盖率。内存高效。所有的JSON对象都只有一个指针(一个Union的最大尺寸)和一个枚举类型(1 byte)的开销。默认泛化下使用 C++ 数据类型: std::string 对应stringint64_t 或者 double 对应 numbersstd::map对应objectsstd::vector 对应 arrays,bool 对应 Booleans根据需要将 basic_json 根据需要作为模板。 速度。 诚然目前有更快的JSON库,但是如果你的目标是在你的项目中,快速使用JSON,这个库是你较好的选择,如果你知道如何使用 std::vector 或者 std::map 你已经准备好必要的知识了。 2. Examples 2.1 创建JSON 对象

假设我们需要创建一下的JSON 对象

{ "pi": 3.141, "happy": true, "name": "Niels", "nothing": null, "answer": { "everything": 42 }, "list": [1, 0, 2], "object": { "currency": "USD", "value": 42.99 } }

我们可以使用一下两种方式:

// create an empty structure (null) // 创建一个空结构体 null json j; // add a number that is stored as double (note the implicit conversion of j to an object) // 添加一个数字并作为double 存储,(注意: j 会被隐式转换为 object) j["pi"] = 3.141; // add a Boolean that is stored as bool // 添加一个 Boolean 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} }; // instead, you could also write (which looks very similar to the JSON above) json j2 = { {"pi", 3.141}, {"happy", true}, {"name", "Niels"}, {"nothing", nullptr}, {"answer", { {"everything", 42} }}, {"list", {1, 0, 2}}, {"object", { {"currency", "USD"}, {"value", 42.99} }} }; 2.2 序列化和反序列化 2.2.1 与string 交互

你可以创建带有_json方式结尾的字符串创建json

json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; // or even nicer with a raw string literal auto j2 = R"( { "happy": true, "pi": 3.141 } )"_json; 2.2.2 使用json::parse auto j3 = json::parse(R"({"happy": true, "pi": 3.14})"); 2.2.3 dump() 转换为字符串

Note: 这个库只支持 UTF-8,当遇到其他编码格式并调用 .dump 时,可能会抛出 json::error_handler_t::replace 或者 json::error_handler_t::ignore 的异常

// 显示转换 std::string s = j.dump(); // {"happy": true, "pi": 3,14} 2.2.4 从流中读取、保存 // 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.2.5 从迭代器中

可以从一个迭代器范围中解析JSON 对象。任何的顺序容器(std::array, std::vector, std::deque, std::forward_list, std::list) 的值可用于创建 JSON array (e.g int, float, bool, string, STL 容器)

std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'}; json j = json::parse(v.begin(), v.end()); // 或者 解析[begin, end) json j = json::parse(v); std::vector<int> c_vector {1, 2, 3, 4}; json j_vec(c_vector); // [1, 2, 3, 4] std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6}; json j_deque(c_deque); // [1.2, 2.3, 3.4, 5.6] std::list<bool> c_list {true, true, false, true}; json j_list(c_list); // [true, true, false, true] std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; json j_flist(c_flist); // [12345678909876, 23456789098765, 34567890987654, 45678909876543] std::array<unsigned long, 4> c_array {{1, 2, 3, 4}}; json j_array(c_array); // [1, 2, 3, 4] std::set<std::string> c_set {"one", "two", "three", "four", "one"}; json j_set(c_set); // only one entry for "one" is used // ["four", "one", "three", "two"] std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"}; json j_uset(c_uset); // only one entry for "one" is used // maybe ["two", "three", "four", "one"] std::multiset<std::string> c_mset {"one", "two", "one", "four"}; json j_mset(c_mset); // both entries for "one" are used // maybe ["one", "two", "one", "four"] std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"}; json j_umset(c_umset); // both entries for "one" are used // maybe ["one", "two", "one", "four"]

从字典(关系型容器)中解析: 同样关联容器(std::set, std::multiset, std::unordered_set, std::unordered_multiset), 元素的顺序取决于在对应STL容器中顺序。

std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} }; json j_map(c_map); // {"one": 1, "three": 3, "two": 2 } std::unordered_map<const char*, double> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} }; json j_umap(c_umap); // {"one": 1.2, "two": 2.3, "three": 3.4} std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; json j_mmap(c_mmap); // only one entry for key "three" is used // maybe {"one": true, "two": true, "three": true} std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; json j_ummap(c_ummap); // only one entry for key "three" is used // maybe {"one": true, "two": true, "three": true} 2.2.6 自定义类型中解析 struct MyContainer { void advance(); const char& get_current(); }; struct MyIterator { using difference_type = std::ptrdiff_t; using value_type = char; using pointer = const char*; using reference = const char&; using iterator_category = std::input_iterator_tag; MyIterator& operator++() { MyContainer.advance(); return *this; } bool operator!=(const MyIterator& rhs) const { return rhs.target != target; } reference operator*() const { return target.get_current(); } MyContainer* target = nullptr; }; MyIterator begin(MyContainer& tgt) { return MyIterator{&tgt}; } MyIterator end(const MyContainer&) { return {}; } void foo() { MyContainer c; json j = json::parse(c); } 2.3 Array 2.3.1 STL 风格访问 json j; j.push_back("foo"); j.push_back(1); j.push_back(true); j.emplace_back(1.78); // 访问 for (json::iterator it = j.begin(); it != j.end(); ++it) { std::cout << *it << '\n'; } for (auto& element : j) { std::cout << element << '\n'; } // 其他特性 j.size(); // 4 j.empty(); // false j.type(); // json::value_t::array j.clear(); 2.3.2 getter and setter // getter / setter const auto tmp = j[0].get<std::string>(); j[1] = 43; bool foo = j.at(2); 2.3.3 对比 j == R"(["foo", 1, true, 1.78])"_json; // true 2.3.4 类型检查 j.is_null(); j.is_boolean(); j.is_number(); j.is_string(); j.is_object(); j.is_array(); 2.4 Object 字典 2.4.1 读写 json o; o["foo"] = 23; o["bar"] = false; o["baz"] = 3.2; // emplace o.emplace("weathre", "sunny"); // 迭代访问 for ( json::iterator it = o.begin(); it != o.end(); ++it) { std::cout << it.key() << ":" << it.value() << "\n"; } for(auto& el : o.items) { std::cout << el.key() << " : " << el.value() << '\n'; } for(auto& [key, value] : o.items()) { std::std << key << ":" << value << '\n'; } 2.4.2 查找 if (o.contains("foo")) { } if(o.find("foo") != o.end()) { } int foo_present = o.count("foo"); // 1 int fob_present = o.count("fob"); // 0 2.4.3 删除 o.erase("foo"); 2.5 JSON Pointer and JSON Patch

JSON Pointer 作为处理结构化值得替代方法,除此以外,JSON Patch 允许描述两个JSON values 的差异。

// a JSON value json j_original = R"({ "baz": ["one", "two", "three"], "foo": "bar" })"_json; // access members with a JSON pointer (RFC 6901) j_original["/baz/1"_json_pointer]; // "two" // a JSON patch (RFC 6902) json j_patch = R"([ { "op": "replace", "path": "/baz", "value": "boo" }, { "op": "add", "path": "/hello", "value": ["world"] }, { "op": "remove", "path": "/foo"} ])"_json; // apply the patch json j_result = j_original.patch(j_patch); // { // "baz": "boo", // "hello": ["world"] // } // calculate a JSON patch from two JSON values json::diff(j_result, j_original); // [ // { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, // { "op": "remove","path": "/hello" }, // { "op": "add", "path": "/foo", "value": "bar" } // ]


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #C #nlohmann #JSON #