1. JSON概述
JSON: JavaScript 对象表示法( JavaScript Object Notation) 。是一种轻量级的数据交换格式。 它基于ECMAScript的一个子集。许多编程语言都很容易找到JSON 解析器和 JSON 库。 JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。不同语言的不同json库对json标准的支持不尽相同,为了能让尽可能多的json库都能正常解析和生成json,定义JSON的规范很重要,推荐一个JSON规范《JSON风格指南》。
2. 常用C&C++ JSON库
常用且知名度较高的C&C++的JSON库有cJSON、json-c、JsonCpp等,腾讯员工开源的一个RapidJSON以高性能著称。C&C++的JSON库比较见RapidJSON作者的比较nativejson-benchmark。
3. 非常简单易用的CJsonObject
CJsonObject是基于cJSON全新开发一个C++版的JSON库,CJsonObject的最大优势是轻量(只有4个文件,拷贝到自己代码里即可,无须编译成库,且跨平台和编译器)、简单好用,开发效率极高。 我一直使用的json库是一个较老版本的cJSON,cJSON的好处是简单易用,而且只有两个文件,直接复制到自己的代码中就可以用。cJSON也有一个非常容易让初用者头痛的地方,一不小心就造成内存泄漏了。为此,我基于cJSON封装了一个C++版的CJsonObject,该库比cJSON更简单易用,且只要不是有意不释放内存就不会发生内存泄漏。用CJsonObject的好处在于完全不用文档,看完Demo马上就会用,不明白的看一下头文件就知道,所有函数都十分通俗易懂,最为关键的一点是解析JSON和生成JSON的编码效率非常高。当然,毕竟是经过cJSON封装而来,效率会略低于cJSON,cJSON不支持的CJsonObject也不支持。个人认为,既然已经选了json,那一点点的解析性能差异就不重要了,如果追求性能可以选protobuf。CJsonObject在我最近4年做过的8个项目中广泛应用,目前有超过20人在使用,至于是否有离职同事带到其他团队去了就不太清楚。CJsonObject非常简单易用,且表现稳定,2018年5月我把它开源https://github.com/Bwar/CJsonObject,并将持续维护。
来看看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执行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
[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_ */
作者:Bwar 出处:https://www.cnblogs.com/bwar/
Bwar倾力打造的高性能网络框架Nebula:https://github.com/Bwar/Nebula
原创文章如转载,请注明出处。本文首发于博客园。