c++中nlohmann?json的基本使用教程
一.json.hpp庫下載及安裝
1.1 開源地址及引入方法
nlohmann json的開源項目地址,其中有對json使用方法的詳細(xì)說明:
https://github.com/nlohmann/json#serialization–deserialization
對于我們項目中要使用nlohmann json工具,只需要引入json.hpp這一個文件,其中包含所有接口函數(shù),正如其文檔中所述json.hpp文件在single_include/nlohmann目錄下,我們只需要下載該文件即可:
git clone https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp
如上圖片所示,使用json.hpp文件需要關(guān)注兩點:
一是:#include <nlohmann/json.hpp>頭文件路徑的引入,這里將json.hpp文件放到linux系統(tǒng)中的/usr/local/include路徑下,這是系統(tǒng)默認(rèn)頭文件路徑,在編譯時系統(tǒng)會自動查找該路徑。我們在/usr/local/include路徑下創(chuàng)建/nlohmann/json.hpp,如下圖所示:
二是:在編譯時需要指定c++11標(biāo)準(zhǔn),-std=c++11。
1.2 demo程序測試
jsontest.cpp:
#include <iostream> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; // for convenience using json = nlohmann::json; int main() { auto config_json = json::parse(R"({"happy": true, "pi": 3.141})"); //構(gòu)建json對象 cout << config_json << endl; //輸出json對象值 return 0; }
編譯:
g++ jsontest.cpp -std=c++11
輸出結(jié)果:
{“happy”:true,“pi”:3.141}
二.nlohmann json基本操作
2.1 由basic value創(chuàng)建json
兩種方式創(chuàng)建json對象:賦值構(gòu)造+直接構(gòu)造
jsontest.cpp:
#include <iostream> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; // for convenience int main() { //方式一:賦值構(gòu)造 json j1; j1["name"]="LeBorn Jame";//字符串 j1["number"]=23; //整數(shù) j1["man"]=true; //布爾值 j1["children"]={"LeBorn Jr","Bryce Maximus","Zhuri"};//數(shù)組 j1["behavior"]["funny"]="gigigigigigi"; //對象中元素值 j1["wife"]={{"name","Savannah Brinson"},{"man",false}};//對象 //方式二:直接構(gòu)造 json j2={ {"name","LeBorn Jame"}, {"number",23}, {"man",true}, {"children",{"LeBorn Jr","Bryce Maximus","Zhuri"}}, {"behavior",{{"funny","gigigigigigi"}}}, {"wife",{{"name","Savannah Brinson"},{"man",false}}} }; cout << "j1: "<<j1 << endl; //輸出json對象值 cout << "j2: "<<j2 << endl; //輸出json對象值 return 0; }
編譯:
g++ jsontest.cpp -std=c++11
輸出結(jié)果:
j1: {“behavior”:{“funny”:“gigigigigigi”},“children”:[“LeBorn Jr”,“Bryce Maximus”,“Zhuri”],“man”:true,“name”:“LeBorn Jame”,“number”:23,“wife”:{“man”:false,“name”:“Savannah Brinson”}}
j2: {“behavior”:{“funny”:“gigigigigigi”},“children”:[“LeBorn Jr”,“Bryce Maximus”,“Zhuri”],“man”:true,“name”:“LeBorn Jame”,“number”:23,“wife”:{“man”:false,“name”:“Savannah Brinson”}}
2.2 由json對象得到basic value
#include <iostream> #include <string> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; // for convenience int main() { //構(gòu)建一個json對象hututu json hututu = { {"name","hututu"}, {"age",18}, {"gender",'m'}, {"score",88.99}, {"location",{"aaa","bbb","ccc"}}, }; //方式一 auto name = hututu["name"].get<std::string>(); //獲取“name”對應(yīng)的value值,并轉(zhuǎn)為string類型 cout<<"name = "<<name<<endl; cout<<"type name = "<<typeid(name).name()<<endl; cout<<"----------------------"<<endl; //方式二 auto location0 = hututu["location"][0].get<std::string>(); auto location1 = hututu["location"][1].get<std::string>(); auto location2 = hututu["location"].at(2).get<std::string>(); cout<<"location0 = "<<location0<<endl; cout<<"location1 = "<<location1<<endl; cout<<"location2 = "<<location2<<endl; return 0; }
輸出結(jié)果:
name = hututu
type name = Ss
location0 = aaa
location1 = bbb
location2 = ccc
2.3 像操作stl container一樣操作json value
#include <iostream> #include <string> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; // for convenience int main() { //構(gòu)建一個json對象animalArray json animalArray={"cat","dog"};//定義一個數(shù)組類型的json對象 animalArray.push_back("pig");//添加元素 animalArray.emplace_back("duck");//C++11新方式添加元素,減少申請內(nèi)存 cout<<"animalArray: "<<animalArray<<endl; //使用is_array()函數(shù)判斷對象類型,使用empty函數(shù)判斷數(shù)量是否為空 if(animalArray.is_array() && !animalArray.empty()) { auto size=animalArray.size(); //使用size函數(shù)獲取元素數(shù)量 cout<<"animalArray size: "<<size<<endl; auto animalLast=animalArray.at(size-1).get<std::string>(); cout<<"animalArray[size-1]: "<<animalLast<<endl; cout<<"/--------------------/"<<endl; } json animalObject={{"kind","dog"},{"height",50}};//定義一個對象類型的json對象 animalObject.push_back({"color","red"});//插入元素 animalObject.erase("kind");//刪除鍵值 cout<<"animalObject: "<<animalObject<<endl; animalObject["height"] = 99; //通過key修改value值 //判斷是否含有某個鍵值方式一 if(animalObject.contains("height"))//通過contains函數(shù)判斷是否包含某個key { auto height=animalObject["height"].get<double>(); cout<<"方式一:height: "<<height<<endl; } //判斷是否含有某個鍵值方式二 auto size=animalObject.count("height");//通過count函數(shù)計算某一個鍵的數(shù)量 if(size>0) { cout<<"方式二:存在height鍵值"<<endl; } //判斷是否含有某個鍵值方式三 auto iter=animalObject.find("height");//通過find函數(shù)查找某個鍵的迭代器 if(iter!=animalObject.end()) { cout<<"方式三:存在height鍵值"<<endl; } //遍歷輸出鍵值方式1 cout<<"遍歷輸出鍵值方式1:"<<endl; for(auto item:animalObject.items()) { std::cout<<item.key()<<" "<<item.value()<<std::endl; } //遍歷輸出鍵值方式2 cout<<"遍歷輸出鍵值方式2:"<<endl; for(auto iter=animalObject.begin();iter!=animalObject.end();++iter) { cout<<iter.key()<<" "<<iter.value()<<std::endl; } return 0; }
輸出結(jié)果:
animalArray: [“cat”,“dog”,“pig”,“duck”]
animalArray size: 4
animalArray[size-1]: duck
/--------------------/
animalObject: {“color”:“red”,“height”:50}
方式一:height: 99
方式二:存在height鍵值
方式三:存在height鍵值
遍歷輸出鍵值方式1:
color “red”
height 99
遍歷輸出鍵值方式2:
color “red”
height 99
三.json序列化與反序列化
3.1 json value和string
#include <iostream> #include <string> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; // for convenience int main() { //反序列化構(gòu)建json對象,兩種方式 json hututu1 = "{\"name\":\"hututu\",\"age\":18,\"score\":88.99}"_json;//方式1,通過"_json"實現(xiàn)反序列化 auto temp = R"({"name":"hututu","age":18,"score":88.99})";//使用原生字符串關(guān)鍵字R來避免轉(zhuǎn)移字符,但這一句并沒有序列化,hututu2只保存字符串而已,需要結(jié)合方式3實現(xiàn)反序列化 json hututu2 = json::parse(temp);//方式2,通過靜態(tài)函數(shù)"parse"實現(xiàn)反序列化 cout<<"/----------反序列化-----------/"<<endl; cout<<"hututu1 = "<<hututu1<<endl; cout<<"hututu2 = "<<hututu2<<endl; cout<<"/----------序列化-----------/"<<endl; //序列化(Serialization):dump(number),number為打印出的空格數(shù) std::string hututu1_string=hututu1.dump();//animal1值為{"kind":"dog","height":50} std::string hututu2_string=hututu2.dump(4); cout<<"hututu1_string = "<<hututu1_string<<endl; cout<<"hututu2_string = "<<hututu2_string<<endl; return 0; }
輸出結(jié)果:
/----------反序列化-----------/
hututu1 = {“age”:18,“name”:“hututu”,“score”:88.99}
hututu2 = {“age”:18,“name”:“hututu”,“score”:88.99}
/----------序列化-----------/
hututu1_string = {“age”:18,“name”:“hututu”,“score”:88.99}
hututu2_string = {
“age”: 18,
“name”: “hututu”,
“score”: 88.99
}
3.2 json對象和文件輸入輸出轉(zhuǎn)換
#include <iostream> //文件操作頭文件 #include <string> #include <fstream> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; // for convenience int main() { //上述操作適用于istream和ostream的子類,比如我們經(jīng)常會用到的ifstream和ofstream //從.json文件中讀取內(nèi)容到j(luò)son對象中 std::ifstream in("./person.json");//打開文件,關(guān)聯(lián)到流in json hututu={"111","222"}; //定義一個json對象為hututu,有初始內(nèi)容,但是會被覆蓋 in>>hututu; //從流in中(也就是./person.json文件)讀取內(nèi)容到j(luò)son對象中,會覆蓋之前內(nèi)容 in.close(); //關(guān)閉文件流in hututu["aaa"]="bbb"; //添加json對象內(nèi)容 cout << hututu << endl; //輸出json對象值 //輸出json對象內(nèi)容到文件中,并生成新的文件 std::ofstream out("./new.json"); //創(chuàng)建文件./new.json,并關(guān)聯(lián)到流out hututu["name"]="new name"; //更改hututu對象的內(nèi)容 out<<std::setw(4)<<hututu; //輸出json對象hututu信息到文件./new.json中,std::setw(4)用于設(shè)置增加打印空格 out.close(); //關(guān)閉文件流out return 0; }
./person.json文件內(nèi)容
{
“name”:“hututu”,
“age”:18,
“gender”:“m”,
“score”:88.99
}
執(zhí)行程序后,輸出的json對象內(nèi)容如下,也就是從./person.json文件中讀取的信息:
{“aaa”:“bbb”,“age”:18,“gender”:“m”,“name”:“hututu”,“score”:88.99}
同時在當(dāng)前目錄下生成新的文件./new.json,內(nèi)容如下所示:
{
“aaa”: “bbb”,
“age”: 18,
“gender”: “m”,
“name”: “new name”,
“score”: 88.99
}
3.3 json value和自定義對象
在自定義對象命名空間中定義兩個函數(shù)即可像basic value一樣進(jìn)行反序列化和序列化:from_json(const json& j,T& value)、to_json(json& j,const T& value)
#include <iostream> //文件操作頭文件 #include <string> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; class person { public: person(){} //默認(rèn)構(gòu)造函數(shù) person(string m_name,int m_age,double m_score):name(m_name),age(m_age),score(m_score){}; public: string name; int age; double score; void display() { cout<<"person name = "<<this->name<<endl; cout<<"person age = "<<this->age<<endl; cout<<"person score = "<<this->score<<endl; } }; //定義from_json(const json& j,T& value)函數(shù),用于序列化 //json對象----->class對象 void from_json(const json& j,person& hututu) { hututu.name=j["name"].get<std::string>(); hututu.age=j["age"].get<int>(); hututu.score=j["score"].get<double>(); } //定義to_json(json& j,const T& value)函數(shù),用于反序列化 //class對象----->json對象 void to_json(json& j,const person& hututu) { j["name"]=hututu.name; j["age"]=hututu.age; j["score"]=hututu.score; } // 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) { // j.at("name").get_to(p.name); // j.at("address").get_to(p.address); // j.at("age").get_to(p.age); // } //main.cpp文件 int main() { person hututu{"hututu",18,88.99};//定義一個person對象為hututu cout<<"/----------to json,方式1:json=class隱式轉(zhuǎn)換-----------/"<<endl; json j1=hututu; //class to json,隱式調(diào)用to_json函數(shù) cout<<"j1 = "<<j1<<endl; //輸出json對象值 cout<<"/----------to json,方式2:調(diào)用to_json函數(shù)-----------/"<<endl; json j2; to_json(j2,hututu); //to json,調(diào)用to_json函數(shù) cout<<"j2 = "<<j2<<endl; //輸出json對象值 cout<<"/----------from json,方式1:調(diào)用from_json函數(shù)-----------/"<<endl; j1["name"]="new name"; //修改json對象數(shù)據(jù) cout<<"new j1 = "<<j1<<endl; //輸出json對象值 person hututu_new; from_json(j1,hututu_new); //json---->class hututu_new.display(); //輸出person對象內(nèi)容 cout<<"/----------from json,方式2:調(diào)用.get函數(shù)-----------/"<<endl; person hututuNew = j2.get<person>();//像basic value一樣通過get函數(shù)獲取值,將其值直接賦值給自定義對象 hututuNew.display(); return 0; }
執(zhí)行結(jié)果:
/----------to json,方式1:json=class隱式轉(zhuǎn)換-----------/
j1 = {“age”:18,“name”:“hututu”,“score”:88.99}
/----------to json,方式2:調(diào)用to_json函數(shù)-----------/
j2 = {“age”:18,“name”:“hututu”,“score”:88.99}
/----------from json,方式1:調(diào)用from_json函數(shù)-----------/
new j1 = {“age”:18,“name”:“new name”,“score”:88.99}
person name = new name
person age = 18
person score = 88.99
/----------from json,方式2:調(diào)用.get函數(shù)-----------/
person name = hututu
person age = 18
person score = 88.99
四.NLOHMANN_DEFINE_TYPE_INTRUSIVE宏的使用
4.1 宏的定義
JSON for Modern C++ 中為方便序列化和反序列化定義了兩宏,如下
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, …) 將在要為其創(chuàng)建代碼的類/結(jié)構(gòu)的命名空間內(nèi)定義。
NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, …) 將在要為其創(chuàng)建代碼的類/結(jié)構(gòu)中定義。 該宏還可以訪問私有成員。
進(jìn)一步查看代碼:
/*! @brief macro @def NLOHMANN_DEFINE_TYPE_INTRUSIVE @since version 3.9.0 */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } /*! @brief macro @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE @since version 3.9.0 */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
4.2 宏的使用
可以看出上述的宏主要實現(xiàn)了from_json和to_json兩個函數(shù)的功能,使用時需要在一個類中調(diào)用該宏,并傳入(類名,參數(shù)1,參數(shù)2,參數(shù)3…)使用,這樣在json對象和class對象之間之間直接賦值可以完成相互轉(zhuǎn)換,具體用法如下:
#include <iostream> //文件操作頭文件 #include <string> #include <nlohmann/json.hpp> //引入json.hpp,該文件已經(jīng)放在系統(tǒng)默認(rèn)路徑:/usr/local/include/nlohmann/json.hpp using namespace std; using json = nlohmann::json; class person { public: string name; int age; double score; void display() { cout<<"person name = "<<this->name<<endl; cout<<"person age = "<<this->age<<endl; cout<<"person score = "<<this->score<<endl; } // 類名,成員1,成員2,成員3 NLOHMANN_DEFINE_TYPE_INTRUSIVE(person, name, age, score); }; //main.cpp文件 int main() { person hututu{"hututu",18,88.99};//定義一個person對象為hututu cout<<"/----------調(diào)用宏實現(xiàn):to json-----------/"<<endl; json j1 = hututu; cout << j1<< endl; cout << j1.dump() << endl; cout<<"/----------調(diào)用宏實現(xiàn):from json-----------/"<<endl; j1["name"]="new name"; person hututu_new = j1; hututu_new.display(); return 0; }
輸出結(jié)果:
/----------調(diào)用宏實現(xiàn):to json-----------/
{“age”:18,“name”:“hututu”,“score”:88.99}
{“age”:18,“name”:“hututu”,“score”:88.99}
/----------調(diào)用宏實現(xiàn):from json-----------/
person name = new name
person age = 18
person score = 88.99
總結(jié)
到此這篇關(guān)于c++中nlohmann json基本使用的文章就介紹到這了,更多相關(guān)c++ nlohmann json使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Visual Studio 2022無法打開源文件的解決方式
這篇文章主要介紹了Visual Studio 2022無法打開源文件的解決方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01C++實現(xiàn)雙目立體匹配Census算法的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C++實現(xiàn)雙目立體匹配Census算法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-08-08VS2019開發(fā)簡單的C/C++動態(tài)鏈接庫并進(jìn)行調(diào)用的實現(xiàn)
這篇文章主要介紹了VS2019開發(fā)簡單的C/C++動態(tài)鏈接庫并進(jìn)行調(diào)用的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03一文帶你學(xué)習(xí)C++析構(gòu)函數(shù)
在C++中,析構(gòu)函數(shù)是一種特殊類型的成員函數(shù),用于在對象生命周期結(jié)束時被自動調(diào)用,本文我們將介紹C++析構(gòu)函數(shù)的一些重要知識點,并提供相應(yīng)代碼示例,需要的朋友可以參考下2023-05-05