https://github.com/Bwar/CJsonObject
CJsonObject 是C++ CJSON 旧版本的新开发版本。CJsonObject最大的优点是重量轻、简单易用,开发效率很高。CJsonObject 比 CJSON 简单得多,更易于使用。
Bwar 首次使用 cJSON 是在 2013 年开发移动推送项目。当时,虽然cJSON很有用,但很容易忘记释放cJSON分配的内存。2014 年,Bwar 在开发另一个项目时再次使用 cJSON。为了提高cJSON的易用性,提高开发效率,对cJSON进行封装,支持64位整数。在CJsonObject的开发中,CJSON被稍微修改了。
5年来,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;
}
Makefile
CC = gcc
CXX = g++
CFLAGS = -g -O2
CXXFLAG = -O2 -Wall -ggdb -m64 -D_GNU_SOURCE=1 -D_REENTRANT -D__GUNC__
ARCH:=$(shell uname -m)
ARCH32:=i686
ARCH64:=x86_64
ifeq ($(ARCH),$(ARCH64))
SYSTEM_LIB_PATH:=/usr/lib64
else
SYSTEM_LIB_PATH:=/usr/lib
endif
VPATH = . ..
DIRS=$(VPATH)
INC := $(INC)
LDFLAGS := $(LDFLAGS) -D_LINUX_OS_
CPP_SRCS = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp))
C_SRCS = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))
OBJS = $(patsubst %.cpp,%.o,$(CPP_SRCS)) $(patsubst %.c,%.o,$(C_SRCS)) $(patsubst %.cc,%.o,$(CC_SRCS))
TARGET = CJsonObjectTest
all: $(TARGET)
CJsonObjectTest:$(OBJS)
$(CXX) -g -o $@ $^ $(LDFLAGS)
%.o:%.cpp
$(CXX) $(INC) $(CXXFLAG) -c -o $@ $< $(LDFLAGS)
%.o:%.cc
$(CXX) $(INC) $(CXXFLAG) -c -o $@ $< $(LDFLAGS)
%.o:%.c
$(CC) $(INC) $(CXXFLAG) -c -o $@ $< $(LDFLAGS)
clean:
rm -f $(OBJS)
rm -f $(TARGET)
运行
[root@lwh demo]# make
g++ -O2 -Wall -ggdb -m64 -D_GNU_SOURCE=1 -D_REENTRANT -D__GUNC__ -c -o demo.o demo.cpp -D_LINUX_OS_
g++ -O2 -Wall -ggdb -m64 -D_GNU_SOURCE=1 -D_REENTRANT -D__GUNC__ -c -o ../CJsonObject.o ../CJsonObject.cpp -D_LINUX_OS_
gcc -O2 -Wall -ggdb -m64 -D_GNU_SOURCE=1 -D_REENTRANT -D__GUNC__ -c -o ../cJSON.o ../cJSON.c -D_LINUX_OS_
g++ -g -o CJsonObjectTest demo.o ../CJsonObject.o ../cJSON.o -D_LINUX_OS_
[root@lwh demo]# ls
CJsonObjectTest demo.cpp demo.o Makefile
[root@lwh 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"]
}
}
[root@lwh demo]#
std::string strTraversingKey;
std::string strTraversingValue;
// while(oJson.GetKey(strTraversingKey)){}
// 每次!从oJson对象中取出一个key并把key设置进strTraversingKey
// 获取成功就返回true,当遍历完所有的key后,返回false
while (oJson.GetKey(strTraversingKey))
{
// oJson.Get(strTraversingKey, strTraversingValue)
// 从oJson对象中取出key=strTraversingKey对应的value,
// 并把value设置进strTraversingValue
if (oJson.Get(strTraversingKey, strTraversingValue))
{
std::cout << strTraversing << " : " << strTraversingValue << std::endl;
}
}
GetKey()遍历不适用于数组,对json数组调用GetKey()将直接返回false。
调用GetKey()函数循环遍历获取当前所在层次的json key,GetKey()返回false表示已取完最后一个key,下次遍历再调用GetKey()将重新从第一个key开始获取。换一种说法,GetKey()遍历json key的返回结果为:true,true,true … true,false; true,true,true … true,false; true,true,true … true,false; 想要遍历多少轮完全由用户自己决定。
如果需要中断一次遍历并重新开始,可以调用ResetTraversing()函数重置遍历。
std::string strTraversingKey;
std::string strTraversingValue;
while(oJson.GetKey(strTraversingKey))
{
if (strTraversingKey == "Auguest")
{
oJson.ResetTraversing();
break;
}
if (oJson.Get(strTraversingKey, strTraversingValue))
{
std::cout << strTraversing << " : " << strTraversingValue << std::endl;
}
}
// 因为上一个遍历中断时调用了ResetTraversing(),所以本次遍历又是从第一个key开始。如果上一个遍历中断时未调用ResetTraversing(),那这次遍历将是从上次终端的位置继续,这通常不是遍历的预期结果,因此,中断遍历时记得ResetTraversing()。
while(oJson.GetKey(strTraversingKey))
{
if (oJson.Get(strTraversingKey, strTraversingValue))
{
std::cout << strTraversing << " : " << strTraversingValue << std::endl;
}
}
__注意:__对Json当前层次的key进行Add()或Delete()操作,将导致当前遍历失效,下次调用GetKey()将获取key从头开始。
Replace()函数对key进行替换,跟value类型无关。
把一个value为int的替换为value为string,或将value替换为object或array都是可以的。但如非必要,建议替换后的value类型跟替换前的value类型相同。
[]的重载是操作JsonObject或JsonArray的,为了方便一层一层往下取嵌套的json,不适用于string、int等基本json类型;
()的重载是Get()系列函数的更便捷的调用,如果十分肯定key是存在的不需要通过Get()的返回值判断是否获取成功,调用()比调用Get()编码要快,不适用于操作JsonObject或JsonArray。
[]和()返回值是不一样的,两者不能混用。
{
"test":[
[{"test":1}],
[{"test":2}]
]
}
CJsonObject对多层嵌套json的操作非常灵活方便,对嵌套json的生成和读取有许多种灵活用法。
neb::CJsonObject oTest;
oTest.AddEmptySubArray("test");
for (int i = 1; i < 3; ++i)
{
neb::CJsonObject oDimension1;
neb::CJsonObject oDimension2;
oDimension2.Add("test", i);
oDimension1.Add(oDimension2);
oTest["test"].Add(oDimension1);
}
std::cout << oTest.ToString() << std::endl;
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
这里给出三种生成上述json数组的方式:
neb::CJsonObject oJson;
oJson.AddEmptySubArray("employees");
oJson["employees"].Add(neb::CJsonObject("{\"firstName\":\"John\" , \"lastName\":\"Doe\"}"));
oJson["employees"].Add(neb::CJsonObject("{\"firstName\":\"Anna\" , \"lastName\":\"Smith\"}"));
oJson["employees"].Add(neb::CJsonObject("{\"firstName\":\"Peter\" , \"lastName\":\"Jones\"}"));
neb::CJsonObject oJson;
oJson.AddEmptySubArray("employees");
oJson["employees"].Add(neb::CJsonObject("{}"));
oJson["employees"][0].Add("firstName", "John");
oJson["employees"][0].Add("lastName", "Doe");
oJson["employees"].Add(neb::CJsonObject("{}"));
oJson["employees"][1].Add("firstName", "Anna");
oJson["employees"][1].Add("lastName", "Smith");
oJson["employees"].Add(neb::CJsonObject("{}"));
oJson["employees"][2].Add("firstName", "Peter");
oJson["employees"][2].Add("lastName", "Jones");
neb::CJsonObject oJson;
neb::CJsonObject oJohn;
neb::CJsonObject oAnna;
neb::CJsonObject oPeter;
oJohn.Add("firstName", "John");
oJohn.Add("lastName", "Doe");
oAnna.Add("firstName", "Anna");
oAnna.Add("lastName", "Smith");
oPeter.Add("firstName", "Peter");
oPeter.Add("lastName", "Jones");
oJson.AddEmptySubArray("employees");
oJson["employees"].Add(oJohn);
oJson["employees"].Add(oAnna);
oJson["employees"].Add(oPeter);