C++的Json解析库:jsoncpp和boost
JSON(JavaScript Object Notation)跟xml一樣也是一種數(shù)據(jù)交換格式,了解json請參考其官網(wǎng)http://json.org,本文不再對json做介紹,將重點介紹c++的json解析庫的使用方法。json官網(wǎng)上列出了各種語言對應的json解析庫,作者僅介紹自己使用過的兩種C++的json解析庫:jsoncpp(v0.5.0)和Boost(v1.34.0)。
?一. 使用jsoncpp解析json
Jsoncpp是個跨平臺的開源庫,首先從http://jsoncpp.sourceforge.net/上下載jsoncpp庫源碼,我下載的是v0.5.0,壓縮包大約107K,解壓,在jsoncpp-src-0.5.0/makefiles/vs71目錄里找到jsoncpp.sln,用VS2003及以上版本編譯,默認生成靜態(tài)鏈接庫。 在工程中引用,只需要include/json及.lib文件即可。
?使用JsonCpp前先來熟悉幾個主要的類:?
Json::Value ? ? 可以表示里所有的類型,比如int,string,object,array等,具體應用將會在后邊示例中介紹。
Json::Reader?? 將json文件流或字符串解析到Json::Value, 主要函數(shù)有Parse。
Json::Writer ? ?與Json::Reader相反,將Json::Value轉化成字符串流,注意它的兩個子類:Json::FastWriter和Json::StyleWriter,分別輸出不帶格式的json和帶格式的json。
?1. 從字符串解析json
[cpp]?view plaincopy2. 從文件解析json
json文件內容:
[cpp]?view plaincopy?解析代碼:
[cpp]?view plaincopy?3. 在json結構中插入json
[cpp]?view plaincopy?4. 輸出json
[cpp]?view plaincopy二. 使用Boost property_tree解析json
property_tree可以解析xml,json,ini,info等格式的數(shù)據(jù),用property_tree解析這幾種格式使用方法很相似。
解析json很簡單,命名空間為boost::property_tree,reson_json函數(shù)將文件流、字符串解析到ptree,write_json將ptree輸出為字符串或文件流。其余的都是對ptree的操作。
解析json需要加頭文件:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
1. 解析json
解析一段下面的數(shù)據(jù):
[html]?view plaincopy2. 構造json
[cpp]?view plaincopy?
三. 兩種解析庫的使用經驗
1. 用boost::property_tree解析字符串遇到"\/"時解析失敗,而jsoncpp可以解析成功,要知道'/'前面加一個'\'是JSON標準格式。
2. boost::property_tree的read_json和write_json在多線程中使用會引起崩潰。
針對1,可以在使用boost::property_tree解析前寫個函數(shù)去掉"\/"中的'\',針對2,在多線程中同步一下可以解決。
我的使用心得:使用boost::property_tree不僅可以解析json,還可以解析xml,info等格式的數(shù)據(jù)。對于解析json,使用boost::property_tree解析還可以忍受,但解析xml,由于遇到問題太多只能換其它庫了。
============================================================================================================
JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式,和xml類似,本文主要對VS2008中使用Jsoncpp解析json的方法做一下記錄。
Jsoncpp是個跨平臺的開源庫,下載地址:http://sourceforge.net/projects/jsoncpp/,我下載的是v0.5.0,壓縮包大約104K。
方法一:使用Jsoncpp生成的lib文件
? ????解壓上面下載的Jsoncpp文件,在jsoncpp-src-0.5.0/makefiles/vs71目錄里找到jsoncpp.sln,用VS2008版本編譯,默認生成靜態(tài)鏈接庫。 在工程中引用,只需要包含include/json下的頭文件及生成的.lib文件即可。
? ????如何包含lib文件:在.cpp文件中#pragma comment(lib."json_vc71_libmt.lib"),在工程屬性中Linker下Input中Additional Dependencies寫入lib文件名字(Release下為json_vc71_libmt.lib,Debug為json_vc71_libmtd.lib)
注意:Jsoncpp的lib工程編譯選項要和VS工程中的編譯選項保持一致。如lib文件工程編譯選項為MT(或MTd),VS工程中也要選擇MT(或MTd),否則會出現(xiàn)編譯錯誤問題,debug和release下生成的lib文件名字不同,注意不要看錯了,當成一個文件來使用(我就犯了這個錯誤)。
方法二:使用Jsoncpp包中的.cpp和.h文件
? ????解壓上面下載的Jsoncpp文件,把jsoncpp-src-0.5.0文件拷貝到工程目錄下,將jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\include\json和jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\src\lib_json目錄里的文件包含到VS工程中,在VS工程的屬性C/C++下General中Additional Include Directories包含頭文件目錄.\jsoncpp-src-0.5.0\include。在使用的cpp文件中包含json頭文件即可,如:#include "json/json.h"。將json_reader.cpp、json_value.cpp和json_writer.cpp三個文件的Precompiled Header屬性設置為Not Using Precompiled Headers,否則編譯會出現(xiàn)錯誤。
jsoncpp 使用詳解
jsoncpp 主要包含三種類型的 class:Value、Reader、Writer。jsoncpp 中所有對象、類名都在 namespace Json 中,包含 json.h 即可。
Json::Value 只能處理 ANSI 類型的字符串,如果 C++ 程序是用 Unicode 編碼的,最好加一個 Adapt 類來適配。
下面是從網(wǎng)上找的代碼示例:
1. 從字符串解析json
? ??const?char*?str?=?"{\"uploadid\":?\"UP000000\",\"code\":?100,\"msg\":?\"\",\"files\":?\"\"}";??
????Json::Reader?reader;??
????Json::Value?root;??
????if?(reader.parse(str,?root))??//?reader將Json字符串解析到root,root將包含Json里所有子元素??
????{??
????????std::string?upload_id?=?root["uploadid"].asString();??//?訪問節(jié)點,upload_id?=?"UP000000"??
????????int?code?=?root["code"].asInt();????//?訪問節(jié)點,code?=?100?
????} ? 2. 從文件解析json
int?ReadJsonFromFile(const?char*?filename)??
{??
????Json::Reader?reader;//?解析json用Json::Reader???
????Json::Value?root;?//?Json::Value是一種很重要的類型,可以代表任意類型。如int,?string,?object,?array?????????
????std::ifstream?is;??
????is.open?(filename,?std::ios::binary?);????
????if?(reader.parse(is,?root,?FALSE))??
????{??
????????std::string?code;??
????????if?(!root["files"].isNull())??//?訪問節(jié)點,Access?an?object?value?by?name,?create?a?null?member?if?it?does?not?exist.??
????????????code?=?root["uploadid"].asString();??
????????
????????code?=?root.get("uploadid",?"null").asString();//?訪問節(jié)點,Return?the?member?named?key?if?it?exist,?defaultValue?otherwise.????
????????int?file_size?=?root["files"].size();??//?得到"files"的數(shù)組個數(shù)??
????????for(int?i?=?0;?i?<?file_size;?++i)??//?遍歷數(shù)組??
????????{??
????????????Json::Value?val_image?=?root["files"][i]["images"];??
????????????int?image_size?=?val_image.size();??
????????????for(int?j?=?0;?j?<?image_size;?++j)??
????????????{??
????????????????std::string?type?=?val_image[j]["type"].asString();??
????????????????std::string?url??=?val_image[j]["url"].asString();?
????????????????printf("type?:?%s,?url?:?%s?\n",?type.c_str(),?url.c_str());
????????????}??
????????}??
????}??
????is.close();??
????return?0;??
}? 3. 向文件中插入json
void?WriteJsonData(const?char*?filename)
{
????Json::Reader?reader;??
????Json::Value?root;?//?Json::Value是一種很重要的類型,可以代表任意類型。如int,?string,?object,?array????????
????std::ifstream?is;??
????is.open?(filename,?std::ios::binary?);????
????if?(reader.parse(is,?root))??
????{??
????????Json::Value?arrayObj;???//?構建對象??
????????Json::Value?new_item,?new_item1;??
????????new_item["date"]?=?"2011-11-11";??
????????new_item1["time"]?=?"11:11:11";??
????????arrayObj.append(new_item);??//?插入數(shù)組成員??
????????arrayObj.append(new_item1);?//?插入數(shù)組成員??
????????int?file_size?=?root["files"].size();??
????????for(int?i?=?0;?i?<?file_size;?++i)??
????????????root["files"][i]["exifs"]?=?arrayObj;???//?插入原json中?
????????std::string?out?=?root.toStyledString();??
????????//?輸出無格式json字符串??
????????Json::FastWriter?writer;??
????????std::string?strWrite?=?writer.write(root);
????????std::ofstream?ofs;
????????ofs.open("test_write.json");
????????ofs?<<?strWrite;
????????ofs.close();
????}??
????is.close();??
}
下面是我寫的 使用 Jsoncpp生成lib文件的工程示例:Jsoncpp測試代碼,使用VS2008編譯通過。
// TestJsoncppCode.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include "TestJsoncppCode.h" #include "include/json/json.h" #include <fstream> #include <string>#pragma comment(lib."json_vc71_libmtd.lib")#ifdef _DEBUG #define new DEBUG_NEW #endif// The one and only application objectCWinApp theApp; using namespace std; CString GetWorkDir() { char pFileName[MAX_PATH]; int nPos = GetCurrentDirectory( MAX_PATH, pFileName); CString csFullPath(pFileName); if( nPos < 0 ) return CString(""); else return csFullPath; }void WriteJsonData(const char* filename) {Json::Reader reader; Json::Value root; // Json::Value是一種很重要的類型,可以代表任意類型。如int, string, object, array... std::ifstream is; is.open (filename, std::ios::binary ); if (reader.parse(is, root)) { Json::Value arrayObj; // 構建對象 Json::Value new_item, new_item1; new_item["date"] = "2011-11-11"; new_item1["time"] = "11:11:11"; arrayObj.append(new_item); // 插入數(shù)組成員 arrayObj.append(new_item1); // 插入數(shù)組成員 int file_size = root["files"].size(); for(int i = 0; i < file_size; ++i) root["files"][i]["exifs"] = arrayObj; // 插入原json中 std::string out = root.toStyledString(); // 輸出無格式json字符串 Json::FastWriter writer; std::string strWrite = writer.write(root);std::ofstream ofs;ofs.open("test_write.json");ofs << strWrite;ofs.close();} is.close(); }int ReadJsonFromFile(const char* filename) { Json::Reader reader;// 解析json用Json::Reader Json::Value root; // Json::Value是一種很重要的類型,可以代表任意類型。如int, string, object, array... std::ifstream is; is.open (filename, std::ios::binary ); if (reader.parse(is, root, FALSE)) { std::string code; if (!root["files"].isNull()) // 訪問節(jié)點,Access an object value by name, create a null member if it does not exist. code = root["uploadid"].asString(); code = root.get("uploadid", "null").asString();// 訪問節(jié)點,Return the member named key if it exist, defaultValue otherwise. int file_size = root["files"].size(); // 得到"files"的數(shù)組個數(shù) for(int i = 0; i < file_size; ++i) // 遍歷數(shù)組 { Json::Value val_image = root["files"][i]["images"]; int image_size = val_image.size(); for(int j = 0; j < image_size; ++j) { std::string type = val_image[j]["type"].asString(); std::string url = val_image[j]["url"].asString(); printf("type : %s, url : %s \n", type.c_str(), url.c_str());} } } is.close(); return 0; } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) {int nRetCode = 0;// initialize MFC and print and error on failureif (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){// TODO: change error code to suit your needs_tprintf(_T("Fatal Error: MFC initialization failed\n"));nRetCode = 1;}else{// TODO: code your application's behavior here.}//1.從字符串解析jsonconst char* str = "{\"uploadid\": \"UP000000\",\"code\": 100,\"msg\": \"\",\"files\": \"\"}"; Json::Reader reader; Json::Value root; if (reader.parse(str, root)) // reader將Json字符串解析到root,root將包含Json里所有子元素 { printf("--------------從字符串讀取JSON---------------\n");std::string upload_id = root["uploadid"].asString(); // 訪問節(jié)點,upload_id = "UP000000" int code = root["code"].asInt(); // 訪問節(jié)點,code = 100 printf("upload_id : %s\ncode : %d \n", upload_id.c_str(), code);} //2.從文件解析jsonCString sTempPath = GetWorkDir() + "\\test_json.json";if (!CFileFind().FindFile(sTempPath)){printf("Not Find JSON File : %s", sTempPath);}else{printf("--------------從文件讀取JSON---------------\n");ReadJsonFromFile(sTempPath);}//3.向文件寫入jsonWriteJsonData(sTempPath);system("pause");return nRetCode; }
總結
以上是生活随笔為你收集整理的C++的Json解析库:jsoncpp和boost的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++ 继承机制易犯的错误
- 下一篇: C++匿名对象调用成员函数