C++JSON庫CJsonObject詳解(輕量簡單好用)
1. JSON概述
JSON: JavaScript 對象表示法( JavaScript Object Notation) 。是一種輕量級的數(shù)據(jù)交換格式。 它基于ECMAScript的一個子集。許多編程語言都很容易找到JSON 解析器和 JSON 庫。 JSON 文本格式在語法上與創(chuàng)建 JavaScript 對象的代碼相同。不同語言的不同json庫對json標(biāo)準(zhǔn)的支持不盡相同,為了能讓盡可能多的json庫都能正常解析和生成json,定義JSON的規(guī)范很重要,推薦一個JSON規(guī)范《JSON風(fēng)格指南》。
2. 常用C&C++ JSON庫
常用且知名度較高的C&C++的JSON庫有cJSON、json-c、JsonCpp等,騰訊員工開源的一個RapidJSON以高性能著稱。C&C++的JSON庫比較見RapidJSON作者的比較nativejson-benchmark。
3. 非常簡單易用的CJsonObject
CJsonObject是基于cJSON全新開發(fā)一個C++版的JSON庫,CJsonObject的最大優(yōu)勢是輕量(只有4個文件,拷貝到自己代碼里即可,無須編譯成庫,且跨平臺和編譯器)、簡單好用,開發(fā)效率極高,對多層嵌套json的讀取和生成使用非常簡單(大部分json解析庫如果要訪問多層嵌套json的最里層非常麻煩)。我一直使用的json庫是一個較老版本的cJSON,cJSON的好處是簡單易用,而且只有兩個文件,直接復(fù)制到自己的代碼中就可以用。cJSON也有一個非常容易讓初用者頭痛的地方,一不小心就造成內(nèi)存泄漏了。為此,我基于cJSON封裝了一個C++版的CJsonObject,該庫比cJSON更簡單易用,且只要不是有意不釋放內(nèi)存就不會發(fā)生內(nèi)存泄漏。用CJsonObject的好處在于完全不用文檔,看完Demo馬上就會用,不明白的看一下頭文件就知道,所有函數(shù)都十分通俗易懂,最為關(guān)鍵的一點是解析JSON和生成JSON的編碼效率非常高。當(dāng)然,畢竟是經(jīng)過cJSON封裝而來,效率會略低于cJSON,cJSON不支持的CJsonObject也不支持。個人認(rèn)為,既然已經(jīng)選了json,那一點點的解析性能差異就不重要了,如果追求性能可以選protobuf。CJsonObject在我最近5年做過的8個項目中廣泛應(yīng)用。CJsonObject非常簡單易用,且表現(xiàn)穩(wěn)定,2018年5月我把它開源https://github.com/Bwar/CJsonObject,并將持續(xù)維護(hù)。
來看看CJsonObject是如何簡單易用:
demo.cpp:
#include <string> #include <iostream> #include "../CJsonObject.hpp" int main() { int iValue; std::string strValue; neb::CJsonObject oJson("{\"refresh_interval\":60," "\"dynamic_loading\":[" "{" "\"so_path\":\"plugins/User.so\", \"load\":false, \"version\":1," "\"cmd\":[" "{\"cmd\":2001, \"class\":\"neb::CmdUserLogin\"}," "{\"cmd\":2003, \"class\":\"neb::CmdUserLogout\"}" "]," "\"module\":[" "{\"path\":\"im/user/login\", \"class\":\"neb::ModuleLogin\"}," "{\"path\":\"im/user/logout\", \"class\":\"neb::ModuleLogout\"}" "]" "}," "{" "\"so_path\":\"plugins/ChatMsg.so\", \"load\":false, \"version\":1," "\"cmd\":[" "{\"cmd\":2001, \"class\":\"neb::CmdChat\"}" "]," "\"module\":[]" "}" "]" "}"); std::cout << oJson.ToString() << std::endl; std::cout << "-------------------------------------------------------------------" << std::endl; std::cout << oJson["dynamic_loading"][0]["cmd"][1]("class") << std::endl; oJson["dynamic_loading"][0]["cmd"][0].Get("cmd", iValue); std::cout << "iValue = " << iValue << std::endl; oJson["dynamic_loading"][0]["module"][0].Get("path", strValue); std::cout << "strValue = " << strValue << std::endl; std::cout << "-------------------------------------------------------------------" << std::endl; oJson.AddEmptySubObject("depend"); oJson["depend"].Add("nebula", "https://github.com/Bwar/Nebula"); oJson["depend"].AddEmptySubArray("bootstrap"); oJson["depend"]["bootstrap"].Add("BEACON"); oJson["depend"]["bootstrap"].Add("LOGIC"); oJson["depend"]["bootstrap"].Add("LOGGER"); oJson["depend"]["bootstrap"].Add("INTERFACE"); oJson["depend"]["bootstrap"].Add("ACCESS"); std::cout << oJson.ToString() << std::endl; std::cout << "-------------------------------------------------------------------" << std::endl; std::cout << oJson.ToFormattedString() << std::endl; }
Demo執(zhí)行結(jié)果:
[bwar@nebula demo]$ ./CJsonObjectTest {"refresh_interval":60,"dynamic_loading":[{"so_path":"plugins/User.so","load":false,"version":1,"cmd":[{"cmd":2001,"class":"neb::CmdUserLogin"},{"cmd":2003,"class":"neb::CmdUserLogout"}],"module":[{"path":"im/user/login","class":"neb::ModuleLogin"},{"path":"im/user/logout","class":"neb::ModuleLogout"}]},{"so_path":"plugins/ChatMsg.so","load":false,"version":1,"cmd":[{"cmd":2001,"class":"neb::CmdChat"}],"module":[]}]} ------------------------------------------------------------------- neb::CmdUserLogout iValue = 2001 strValue = im/user/login ------------------------------------------------------------------- {"refresh_interval":60,"dynamic_loading":[{"so_path":"plugins/User.so","load":false,"version":1,"cmd":[{"cmd":2001,"class":"neb::CmdUserLogin"},{"cmd":2003,"class":"neb::CmdUserLogout"}],"module":[{"path":"im/user/login","class":"neb::ModuleLogin"},{"path":"im/user/logout","class":"neb::ModuleLogout"}]},{"so_path":"plugins/ChatMsg.so","load":false,"version":1,"cmd":[{"cmd":2001,"class":"neb::CmdChat"}],"module":[]}],"depend":{"nebula":"https://github.com/Bwar/Nebula","bootstrap":["BEACON","LOGIC","LOGGER","INTERFACE","ACCESS"]}} ------------------------------------------------------------------- { "refresh_interval": 60, "dynamic_loading": [{ "so_path": "plugins/User.so", "load": false, "version": 1, "cmd": [{ "cmd": 2001, "class": "neb::CmdUserLogin" }, { "cmd": 2003, "class": "neb::CmdUserLogout" }], "module": [{ "path": "im/user/login", "class": "neb::ModuleLogin" }, { "path": "im/user/logout", "class": "neb::ModuleLogout" }] }, { "so_path": "plugins/ChatMsg.so", "load": false, "version": 1, "cmd": [{ "cmd": 2001, "class": "neb::CmdChat" }], "module": [] }], "depend": { "nebula": "https://github.com/Bwar/Nebula", "bootstrap": ["BEACON", "LOGIC", "LOGGER", "INTERFACE", "ACCESS"] } }
再來看看頭文件,一看就知道如何使用:
/******************************************************************************* * Project: neb * @file CJsonObject.hpp * @brief Json * @author bwarliao * @date: 2014-7-16 * @note * Modify history: ******************************************************************************/ #ifndef CJSONOBJECT_HPP_ #define CJSONOBJECT_HPP_ #include <stdio.h> #include <stddef.h> #include <malloc.h> #include <errno.h> #include <unistd.h> #include <limits.h> #include <math.h> #include <float.h> #include <string> #include <map> #include "cJSON.h" namespace neb { class CJsonObject { public: // method of ordinary json object or json array CJsonObject(); CJsonObject(const std::string& strJson); CJsonObject(const CJsonObject* pJsonObject); CJsonObject(const CJsonObject& oJsonObject); virtual ~CJsonObject(); CJsonObject& operator=(const CJsonObject& oJsonObject); bool operator==(const CJsonObject& oJsonObject) const; bool Parse(const std::string& strJson); void Clear(); bool IsEmpty() const; bool IsArray() const; std::string ToString() const; std::string ToFormattedString() const; const std::string& GetErrMsg() const { return(m_strErrMsg); } public: // method of ordinary json object bool AddEmptySubObject(const std::string& strKey); bool AddEmptySubArray(const std::string& strKey); CJsonObject& operator[](const std::string& strKey); std::string operator()(const std::string& strKey) const; bool Get(const std::string& strKey, CJsonObject& oJsonObject) const; bool Get(const std::string& strKey, std::string& strValue) const; bool Get(const std::string& strKey, int32& iValue) const; bool Get(const std::string& strKey, uint32& uiValue) const; bool Get(const std::string& strKey, int64& llValue) const; bool Get(const std::string& strKey, uint64& ullValue) const; bool Get(const std::string& strKey, bool& bValue) const; bool Get(const std::string& strKey, float& fValue) const; bool Get(const std::string& strKey, double& dValue) const; bool Add(const std::string& strKey, const CJsonObject& oJsonObject); bool Add(const std::string& strKey, const std::string& strValue); bool Add(const std::string& strKey, int32 iValue); bool Add(const std::string& strKey, uint32 uiValue); bool Add(const std::string& strKey, int64 llValue); bool Add(const std::string& strKey, uint64 ullValue); bool Add(const std::string& strKey, bool bValue, bool bValueAgain); bool Add(const std::string& strKey, float fValue); bool Add(const std::string& strKey, double dValue); bool Delete(const std::string& strKey); bool Replace(const std::string& strKey, const CJsonObject& oJsonObject); bool Replace(const std::string& strKey, const std::string& strValue); bool Replace(const std::string& strKey, int32 iValue); bool Replace(const std::string& strKey, uint32 uiValue); bool Replace(const std::string& strKey, int64 llValue); bool Replace(const std::string& strKey, uint64 ullValue); bool Replace(const std::string& strKey, bool bValue, bool bValueAgain); bool Replace(const std::string& strKey, float fValue); bool Replace(const std::string& strKey, double dValue); public: // method of json array int GetArraySize(); CJsonObject& operator[](unsigned int uiWhich); std::string operator()(unsigned int uiWhich) const; bool Get(int iWhich, CJsonObject& oJsonObject) const; bool Get(int iWhich, std::string& strValue) const; bool Get(int iWhich, int32& iValue) const; bool Get(int iWhich, uint32& uiValue) const; bool Get(int iWhich, int64& llValue) const; bool Get(int iWhich, uint64& ullValue) const; bool Get(int iWhich, bool& bValue) const; bool Get(int iWhich, float& fValue) const; bool Get(int iWhich, double& dValue) const; bool Add(const CJsonObject& oJsonObject); bool Add(const std::string& strValue); bool Add(int32 iValue); bool Add(uint32 uiValue); bool Add(int64 llValue); bool Add(uint64 ullValue); bool Add(int iAnywhere, bool bValue); bool Add(float fValue); bool Add(double dValue); bool AddAsFirst(const CJsonObject& oJsonObject); bool AddAsFirst(const std::string& strValue); bool AddAsFirst(int32 iValue); bool AddAsFirst(uint32 uiValue); bool AddAsFirst(int64 llValue); bool AddAsFirst(uint64 ullValue); bool AddAsFirst(int iAnywhere, bool bValue); bool AddAsFirst(float fValue); bool AddAsFirst(double dValue); bool Delete(int iWhich); bool Replace(int iWhich, const CJsonObject& oJsonObject); bool Replace(int iWhich, const std::string& strValue); bool Replace(int iWhich, int32 iValue); bool Replace(int iWhich, uint32 uiValue); bool Replace(int iWhich, int64 llValue); bool Replace(int iWhich, uint64 ullValue); bool Replace(int iWhich, bool bValue, bool bValueAgain); bool Replace(int iWhich, float fValue); bool Replace(int iWhich, double dValue); private: CJsonObject(cJSON* pJsonData); private: cJSON* m_pJsonData; cJSON* m_pExternJsonDataRef; std::string m_strErrMsg; std::map<unsigned int, CJsonObject*> m_mapJsonArrayRef; std::map<std::string, CJsonObject*> m_mapJsonObjectRef; }; } #endif /* CJSONHELPER_HPP_ */
如果覺得CJsonObject不錯,別忘了給個star,謝謝。
到此這篇關(guān)于C++JSON庫CJsonObject詳解(輕量簡單好用)的文章就介紹到這了,更多相關(guān)C++JSON庫CJsonObject內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解state狀態(tài)模式及在C++設(shè)計模式編程中的使用實例
這篇文章主要介紹了state狀態(tài)模式及在C++設(shè)計模式編程中的使用實例,在設(shè)計模式中策略用來處理算法變化,而狀態(tài)則是透明地處理狀態(tài)變化,需要的朋友可以參考下2016-03-03C++結(jié)構(gòu)體初始化的10種寫法總結(jié)
這篇文章主要為大家詳細(xì)介紹了10種C++中結(jié)構(gòu)體初始化的寫法,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04C++11/14 線程的創(chuàng)建與分離的實現(xiàn)
這篇文章主要介紹了C++11/14 線程的創(chuàng)建與分離的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01一篇文章帶你用C語言玩轉(zhuǎn)結(jié)構(gòu)體
本文主要介紹C語言 結(jié)構(gòu)體的知識,學(xué)習(xí)C語言肯定需要學(xué)習(xí)結(jié)構(gòu)體,這里詳細(xì)說明了結(jié)構(gòu)體并附示例代碼,供大家參考學(xué)習(xí),有需要的小伙伴可以參考下2021-09-09