日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

JSON for Modern C++

發(fā)布時間:2023/12/20 c/c++ 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JSON for Modern C++ 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

JSON(JavaScript Object Notation)是一種非常理想的輕量級數(shù)據(jù)交換格式,基于以下兩種結構:

  • 名-值對的集合 - 在各種語言中,被實現(xiàn)為對象、記錄、結構、字典、散列表、鍵列表、關聯(lián)數(shù)組等;
  • 值的有序列表 - 在大多數(shù)語言中,被實現(xiàn)為數(shù)組、向量、列表、序列等。

JSON for Modern C++ 的設計目標就是:

  • 直觀的語法 - 使用現(xiàn)代 C++ 操作符魔力,使 JSON 成為第一類數(shù)據(jù)類型
  • 微型的集成 - 僅有 json.hpp,無依賴、無復雜構建系統(tǒng),符合 C++11 標準
  • 嚴格的測試 - 單元測試 100% 覆蓋,包括所有的異常行為
  • 高效的內存
  • 更快的速度

集成 JSON for Modern C++ 非常簡單,僅需 json.hpp(GitHub)源文件即可:

#include "json.hpp" // 為方便起見,設置命名空間 using json = nlohmann::json;

對于 GCC 和 Clang 編譯器來說,別忘了打開 C++11 支持,例如 -std=c++11。

下面我們通過一些示例來學習 JSON for Modern C++ 的使用方法。

JSON 作為第一類數(shù)據(jù)類型

直接上栗子:

// 創(chuàng)建一個空結構(null) json j;// 添加一個數(shù)值,存為 double j["pi"] = 3.141; // 添加一個布爾值,存為 bool j["happy"] = true; // 添加一個字符串,存為 std::string j["name"] = "Niels"; // 添加另一個空對象,使用 nullptr j["nothing"] = nullptr; // 添加一個對象內的對象 j["answer"]["everything"] = 42; // 添加一個數(shù)組,存為 std::vector j["list"] = {1, 0, 2}; // 添加另一個對象 j["object"] = {{"currency", "USD"}, {"value", 42.99}};

當然,還可以直接這樣寫:

json j2 = {{"pi", 3.141},{"happy", true},{"name", "Niels"},{"nothing", nullptr},{"answer", {{"everything", 42}}},{"list", {1, 0, 2}},{"object", {{"currency", "USD"},{"value", 42.99}}} };

序列化和反序列化

序列化至字符串 / 反序列化自字符串

通過為字符串字面量附加 _json 可以創(chuàng)建一個 JSON 對象(反序列化):

// 從字符串字面量創(chuàng)建對象 json j = "{\"happy\": true, \"pi\": 3.141}"_json;// 最好是使用原始字符串字面量 auto j2 = R"({"happy": true, "pi": 3.141})"_json;// 顯式地分析 auto j3 = json::parse("{\"happy\": true, \"pi\": 3.141}");

還可以獲取一個字符串表示形式(序列化):

// 顯式地轉換至字符串 std::string s = j.dump()// 傳入縮進空格數(shù),使用良好的打印形式進行序列化 std::cout << j.dump(4) << std::endl;

.dump() 返回的是序列化的值,而 .get<std::string>() 返回的是原始字符串值。

序列化至流 / 反序列化自流

流包括文件、字符串流等,例如:

// 反序列化自標準輸入 json j; std::cin >> j;// 序列化至標準輸出 std::cout << j;// 設置良好打印形式所需的縮進 std::cout << std::setw(4) << j << std::endl;

序列化至文件,或是反序列化自文件,例如:

// 讀入一個 JSON 文件 std::ifstream i("file.json"); json j; i >> j;// 將美化的 JSON 寫入另一個文件 std::ofstream o("pretty.json"); o << std::setw(4) << j << std:endl;

讀自迭代器范圍

可以從一個迭代器范圍中讀取 JSON,迭代器的內容包含連續(xù)的字節(jié)序列,例如 std::vector<std::uint8_t>:

std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};json j = json::parse(v.begin(), v.end()); // 或 json j = json::parse(v);

像 STL 容器一樣訪問

JSON 類的行為就像 STL 容器一般,滿足 ReversibleContainer(可逆容器)的要求,例如:

// 使用 push_back 創(chuàng)建一個數(shù)組 json j; j.push_back("foo"); j.push_back(1); j.push_back(true); // 也可以使用 emplace_back j.emplace_back(1.78);// 在數(shù)組上進行迭代 for (json::iterator it = j.begin(); it != j.end(); ++it) {std::cout << *it << '\n'; }// 基于范圍的 for 循環(huán) for (auto& element : j) {std::cout << element << '\n'; }// 訪問器 getter/setter const std::string tmp = j[0]; j[1] = 42; bool foo = j.at(2);// 比較 j == "[\"foo\", 1, true]"_json; // true// 其他東東 j.size(); // 3 條 j.empty(); // false j.type(); // json::value_t::array j.clear(); // 數(shù)組再次為空// 便利的類型檢測器 j.is_null(); j.is_boolean(); j.is_number(); j.is_object(); j.is_array(); j.is_string();// 創(chuàng)建一個 JSON 對象 json o; o["foo"] = 23; o["bar"] = false; o["baz"] = 3.141;// 也可以使用 emplace o.emplace("weather", "sunny");// 為對象指定迭代成員函數(shù) for (json::iterator it = o.begin(); it != o.end(); ++it) {std::cout << it.key() << " : " << it.value() << "\n"; }// 查找一個條目 if (o.find("foo") != o.end()) {// 找到鍵為 "foo" 的一個條目 }// 使用計數(shù) count() int foo_present = o.count("foo"); // 1 int fob_present = o.count("fob"); // 0// 刪除條目 o.erase("foo");

從 STL 容器轉換至 JSON

任何序列化容器,包括 std::array, std::vector, std::deque, std::forward_list, std::list,都可以用來構建 JSON 數(shù)組。同樣地,關聯(lián)化容器,包括 std::set, std::multiset, std::unordered_set, std::unordered_multiset,也可以用來構建 JSON 數(shù)組。不同的是,數(shù)組中元素的順序是否依賴于 STL 容器中元素的順序。

std::vector<int> c_vector {1, 2, 3, 4}; json j_vec(c_vector);std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6}; json j_deque(c_deque);std::list<bool> c_list {true, true, false, true}; json j_list(c_list);std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; json j_flist(c_flist);std::array<unsigned long, 4> c_array {{1, 2, 3, 4}}; json j_array(c_array);std::set<std::string> c_set {"one", "two", "three", "four", "one"}; json j_set(c_set);std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"}; json j_uset(c_uset);std::multiset<std::string> c_mset {"one", "two", "one", "four"}; json j_mset(c_mset);std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"}; json j_umset(c_umset);

同樣地,任何關聯(lián)的鍵-值容器,包括 std::map, std::multimap, std::unordered_map, std::unordered_multimap, 都可以用來創(chuàng)建 JSON 對象。

std::map<std::string, int> c_map {{"one", 1}, {"two", 2}, {"three", 3}}; json j_map(c_map);std::unordered_map<const char*, double> c_umap {{"one", 1.2}, {"two", 2.3}, {"three", 3.4}}; json j_umap(c_umap);std::multimap<std::string, bool> c_mmap {{"one", true}, {"two", true}, {"three", false}, {"three", true}}; json j_mmap(c_mmap); std::unordered_multimap<std::string, bool> c_ummap {{"one", true}, {"two", true}, {"three", false}, {"three", true}}; json j_ummap(c_ummap);

JSON Pointer 和 JSON Patch

JSON for Modern C++ 庫支持 JSON Pointer(RFC 6901) 和 JSON Patch(RFC 6902),分別用于定位結構化數(shù)值,或描述兩個 JSON 之間的不同。

// 一個 JSON 值 json j_original = R"({"baz":["one", "two", "three"], "foo": "bar"})"_json;// 使用 JSON Pointer 訪問其成員 j_original["/baz/1"_json_pointer]; // => "two"// 一個 JSON Patch json j_patch = R"([{"op": "replace", "path": "/baz", "value": "boo"}, {"op": "add", "path": "/hello", "value": ["world"]}, {"op": "remove", "path": "/foo"}])"_json;// 為 JSON 打補丁 json j_result = j_original.patch(j_patch);// 計算兩個 JSON 值之間的差異 json::diff(j_result, j_original);

隱式轉換

JSON 對象的類型是由表達式所決定的,所存儲的值隱式地進行轉換。例如:

// 字符串 std::string s1 = "Hello, world!"; json js = s1; std::string s2 = js;// 布爾值 bool b1 = true; json jb = b1; bool b2 = jb;// 數(shù)值 int i = 42; json jn = i; double f = jn;

當然,也可以顯式地請求數(shù)值:

std::string vs = js.get<std::string>(); bool vb = jb.get<bool>(); int vi = jn.get<int>();

任意類型轉換

不僅僅是 STL 容器和標量類型,所有類型都可以序列化至 JSON。例如,下面是一個 ns::person 結構:

namespace ns {// 一個簡單的結構,為 person 建模struct person {std::string name;std::string address;int age;}; }

我們來看看自定義結構和 JSON 之間是如何轉換的:

ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};// 轉換至 JSON:將每個值拷貝至 JSON 對象 json j; j["name"] = p.name; j["address"] = p.address; j["age"] = p.age;// 轉換自 JSON:從 JSON 對象中拷貝每個值 ns::person p {j["name"].get<std::string>(),j["address"].get<std::string>(),j["age"].get<int>() };

以上可以工作,但使用了太多的樣板。幸運的是,還可以有更好的方法:

// 創(chuàng)建 person 結構 ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};// 轉換:person → json json j = p;std::cout << j << std::endl;// 轉換:json → person ns::person p2 = j;

要使以上代碼工作,僅需提供兩個函數(shù):

namespace ns {void to_json(json& j, const person& p) {j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};}void from_json(const json& j, person& p) {p.name = j.at("name").get<std::string>();p.name = j.at("address").get<std::string>();p.name = j.at("age").get<int>();} }

二進制格式(CBOR 和 MessagePack)

雖然 JSON 數(shù)據(jù)格式似乎是無所不在的,但卻不怎么適用于網絡數(shù)據(jù)交換。因此,提供 CBOR(Concise Binary Object Representation)和 MessagePack 功能,使得可以將 JSON 數(shù)據(jù)編碼成字節(jié)向量,或是將字節(jié)向量解碼成 JSON 數(shù)據(jù)。

// 創(chuàng)建一個 JSON 數(shù)據(jù) json j = R"({"compact": true, "schema": 0})"_json;// 序列化至 CBOR std::vector<std::uint8_t> v_cbor = json::to_cbor(j); // v_cbor => 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00// 從 CBOR 中返回 JSON json j_from_cbor = json::from_cbor(v_cbor);// 序列化至 MessagePack std::vector<std::uint8_t> v_msgpack = json::to_msgpack(j); // v_msgpack => 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00// 從 MessagePack 中返回 JSON json j_from_msgpack = json::from_msgpack(v_msgpack);

總結

以上是生活随笔為你收集整理的JSON for Modern C++的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。