(給CPP開發者加星標,提升C/C++技能)
導讀:json是一種十分常見的數據交換格式,在接口中被廣泛使用。很多高級語言如python等都對json有良好的支持,方便程式設計師的使用。
然而C++對json沒有很好的內置支持,因此往往要引用一些第三方庫。而網上很多json的包,形形色色種類繁多,但是要麼功能不夠強大,要麼難以使用。
json for modern c++是一款非常好用的json庫,具有語法直觀和使用簡單的特點,並且是用C++11標準編寫的,此外還支持STL和json容器之間的轉換,可謂集方便又強大。
本文推薦給廣大C++程式設計師,相信學習完本文之後,在處理json時一定會得心應手。
————【以下是正文】————
最近學習了json for modern c++的使用,在此總結一些常用功能使用方法。
老規矩,還是先簡單介紹一下什麼是json吧。
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基於ECMAScript的一個子集。JSON採用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網絡傳輸速率)。
今天介紹的json版本是在c++下使用的,是一個開源項目。
GitHub開源項的地址:https://github.com/nlohmann/json
json for modern c++是一個德國大牛nlohmann寫的,該版本的json有以下特點:
1.直觀的語法。
2.整個代碼由一個頭文件組成json.hpp,沒有子項目,沒有依賴關係,沒有複雜的構建系統,使用起來非常方便。
3.使用c++11標準編寫。
4.使用json 像使用STL容器一樣。
5.STL和json容器之間可以相互轉換。
…
將github上的src文件夾裡的json.hpp頭文件下載保存到當前目錄中。
在代碼中包含json.hpp頭文件並引入json作用域
#include "json.hpp"using json = nlohmann::json;
常用功能:一.創建json對象1.使用cin,cout輸入輸出流。
json提供了cin,cout的輸入輸出流的操作符。但需要注意的是,cin要有ctr + D結束輸入。cin會把從標準輸入的內容反序列化,cout會自動把json序列化,以string形式輸出。using namespace std;using json=nlohmann::json;
int main(){ json j; //創建json類 cin>>j; //從cin讀入json對象 cout<<j; //輸出序列化的json return 0;}
/*輸入:{ "pi": 3.141, "happy": true, "name": "Niels", "nothing": null, "answer": { "everything": 42 }, "list": [1, 0, 2], "object": { "currency": "USD", "value": 42.99 }}輸出:{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}*/2.提供根據鍵直接生成鍵值對的方法。(類似於map,如果不存在該鍵的話,就生成一個這個鍵。)
using json = nlohmann::json;using namespace std;
int main() { // 創建一個json對象(null) json j;
//添加一個存儲為double的數字 j["pi"] = 3.141;
// 添加一個布爾值 j["happy"] = true;
// 添加一個存儲為std :: string的字符串 j["name"] = "Niels";
// 通過傳遞nullptr添加另一個空對象 j["nothing"] = nullptr;
// 在對象中添加對象 j["answer"]["everything"] = 42;
//添加一個數組,其存儲為std::vector(使用初始化列表) j["list"] = { 1, 0, 2 };
// 在一個對象中添加另一個對象 j["object"] = { {"currency", "USD"}, {"value", 42.99} };
// 也可以通過直接賦值方式創建json對象,兩種方式創建結果相同 json j2 = { {"pi", 3.141}, {"happy", true}, {"name", "Niels"}, {"nothing", nullptr}, {"answer", { {"everything", 42} }}, {"list", {1, 0, 2}}, {"object", { {"currency", "USD"}, {"value", 42.99} }} }; cout << j << endl; cout << endl; cout << j2 << endl; return 0;}
/*輸出:{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}
{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}*/3.在所有上述情況下,你不需要「告訴」編譯器要使用哪個JSON值。如果你想明確或表達一些邊緣的情況下,可以使用json::array,json::object。
#include <iostream>#include "json.hpp"using json = nlohmann::json;using namespace std;
int main() { json empty_array_explicit = json::array();
json empty_object_implicit = json({}); json empty_object_explicit = json::object();}4.幾點注意
1).array是一個數組,可以用數字直接下標訪問。json array = { "a",6,"xin",8 };cout << array[0] << endl;2)數組中包含一個數組
json array = { {"a",6}, "xin",8 };cout << array[0][0] << endl;3)數組中包含一個對象
json array = { {{"a",6}}, "xin",8 };cout << array[0]["a"] << endl;4).對象中嵌套一個對象和一個數組
json object = { {"a",{{"feng",6}}},{"b",{1,2,3}} }; cout << object << endl;
二.序列化將json對象序列化,成為字符串
1.標準輸出自動序列化
json jstd :: cout << j;std :: cout << std :: setw( 4)<< j << std :: endl;2.使用dump()函數
//顯式轉換為string std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141}
//序列化與漂亮的列印//傳入空格的數量縮進 std::cout << j.dump(4) << std::endl;// 輸出://{// "happy": true,// "pi": 3.141// }三.反序列化將數據流轉化為json對象
1.從標準輸入反序列化
2.通過附加_json到字符串文字來創建對象(反序列化):
json j = " { \" happy \":true,\" pi \":3.141} " _json;
auto j2 = R"( { "happy":true, "pi":3.141 } )" _json;請注意,沒有附加_json後綴,傳遞的字符串文字不會被解析,而只是用作JSON字符串值。也就是說,json j = "{ \"happy\": true, \"pi\": 3.141 }"只存儲字符串"{ "happy": true, "pi": 3.141 }"而不是解析實際的對象。
3.使用json::parse()函數auto j3 = json::parse(" { \" happy \":true,\" pi \":3.141} ");4.從迭代器範圍讀取
您還可以從迭代器範圍讀取JSON; 也就是說,可以從其內容存儲為連續字節序列的迭代器訪問的任何容器,例如std::vector
std :: vector < uint8_t > v = { ' t ',' r ',' u ',' e ' };json j = json :: parse(v.begin(),v.end());
//或std :: vector < uint8_t > v = { ' t ',' r ',' u ',' e ' };json j = json :: parse(v);四.與STL適應nlohmann設計的JSON類,就像一個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';}
const std::string tmp = j[0];j[1] = 42;bool foo = j.at(2);
j == "[\"foo\", 1, true]"_json;
j.size(); j.empty(); j.type(); j.clear();
j.is_null();j.is_boolean();j.is_number();j.is_object();j.is_array();j.is_string();
json o;o["foo"] = 23;o["bar"] = false;o["baz"] = 3.141;
o.emplace("weather", "sunny");
for (json::iterator it = o.begin(); it != o.end(); ++it) { std::cout << it.key() << " : " << it.value() << "\n";}
if (o.find("foo") != o.end()) { }
int foo_present = o.count("foo"); int fob_present = o.count("fob");
o.erase("foo");五.從STL容器轉換任何序列容器(std::array,std::vector,std::deque,std::forward_list,std::list),其值可以被用於構建JSON類型(例如,整數,浮點數,布爾值,字符串類型,或者再次在本節中描述STL容器)可被用於創建JSON陣列。這同樣適用於類似的關聯容器(std::set,std::multiset,std::unordered_set,std::unordered_multiset),但是在這些情況下,陣列的元素的順序取決於元素是如何在各個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);同樣,任何鍵值容器(std::map,std::multimap,std::unordered_map,std::unordered_multimap),其鍵可以構造一個std::string,並且其值可以被用於構建JSON類型(參見上文實施例)可用於創建一個JSON對象。請注意,在多重映射的情況下,JSON對象中僅使用一個鍵,該值取決於STL容器的內部順序。
<br>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對象的類型由要存儲的表達式自動確定。同樣,存儲的值被隱式轉換。
<br>std :: string s1 = 「 Hello,world!」 ;json js = s1;std :: string s2 = js;
bool b1 = true ;json jb = b1;bool b2 = jb;
int i = 42 ;json jn = i;double f = jn;還可以明確要求該值:
std :: string vs = js.get <std :: string>();bool vb = jb.get < bool >();int vi = jn.get < int >();
七.任意類型轉換每個類型都可以以JSON序列化,而不僅僅是STL容器和標量類型。通常情況下,你會做這些事情:
namespace ns { struct person { std::string name; std::string address; int age; };}
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
json j;j["name"] = p.name;j["address"] = p.address;j["age"] = p.age;
ns::person p { j["name"].get<std::string>(), j["address"].get<std::string>(), j["age"].get<int>()};或者,使用一種更簡便的用法
ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};
json j = p;
std::cout << j << std::endl;
ns::person p2 = j;
assert(p == p2);以上是對json for modern c++基本功能的使用總結,如有哪裡有誤,歡迎指出,相互學習交流。
- EOF -
覺得文章不錯,請點讚和在看支持我繼續分享好文。謝謝!
關注『CPP開發者』
看精選C++技術文章 . 加C++開發者專屬圈子
↓↓↓
點讚和在看就是最大的支持❤️