前段时间因为工作内容涉及通讯协议中使用json格式作为双方通讯的基础协议格式,所以有机会接触到了jsoncpp这个开源库。
jsoncpp这个库很不错,当你拿到json数据字符串的时候只需要做:
Json::Reader jr; Json::Value jv; if(!jr.parse(json,jv)) { printf("parse err!\n"); return false; }
这样你即可反序列化出来你想要的数据到jv这个变量里面了,如果你想使用jv获取到json里面的某个数据的话,只需要:
long long age=jv["age"].asInt64();//获取{"age":16}的age值
1:性能上效率比较低,因为Json::Value里面应该用了map这样的方法去查找相对于的字符串去一个一个的查找对象这样效率会比较低
2:比较容易出错,比如你的要获取{“angel”:1} 在代码中写成了 jv[“angry”].asInt64(); 这样编译器并不会报错,
3:你还要干很多检查的事情,如 对方传过来的 angel 是个字符串,你在asInt64()的时候程序就崩溃了,你必须要检查过来的数据类型对不对
4:因为你的工程中很多地方都要用到这个数据,你的整个工程都被病毒式的传染了,到处都是Json::Value
5:还有很多很多问题…
所以要解决以上问题,你必须把json解析到相同的一个结构体中 如:
先定义一下你的通讯协议格式:
{ //先给你的json数据包格式起个名字叫做rpc1 "rpc1" : { "age":16,//年龄 "hp":99,//血 "mp":88//魔法 } }
这样做既可当初文档来用了,其中 这个通讯协议的名字叫做rpc1,里面会传输 age hp mp这三个数据,他们都是整形,如果不传输的话,程序默认他为分别为16 99 88
好了,现在你要写一段代码用jsoncpp解析到你的一个有相同结构的结构体(类)里面
//charset: #ifndef test_json_h #define test_json_h #include <vector> #include <string> #include "json.h" ////////////////////////////////////////////////////////////////////////// //先给你的json数据包格式起个名字叫做rpc1 class rpc1 { private: public: rpc1() { age = 16; hp = 99; mp = 88; } void reset() { age = 16; hp = 99; mp = 88; } bool decode(std::string json) { Json::Reader jr; Json::Value jv; if(!jr.parse(json,jv)) { printf("parse err!\n"); return false; } return decode(jv); } bool decode(Json::Value & jv) { if( jv["age"].type()==Json::intValue || jv["age"].type()==Json::uintValue ) age = jv["age"].asInt64(); if( jv["hp"].type()==Json::intValue || jv["hp"].type()==Json::uintValue ) hp = jv["hp"].asInt64(); if( jv["mp"].type()==Json::intValue || jv["mp"].type()==Json::uintValue ) mp = jv["mp"].asInt64(); return true; } std::string encode2string() { return encode().toStyledString(); } Json::Value encode() { Json::Value root; root["age"]=Json::Value(age); root["hp"]=Json::Value(hp); root["mp"]=Json::Value(mp); return root; } long long age; //年龄 long long hp; //血 long long mp; //魔法 } ; ////////////////////////////////////////////////////////////////////////// #endif //test_json_h
好了,你的代码只是要写出向上面这样才能算完整,里面包含初始化默认值,解析json(decode) 或者是生成json(encode)功能,还包含各种数据类型检查功能以及重置初始值。
使用方法就比较简单了:
rpc1 r; r.decode(str);//str是你要解析的字符串 long long age=r.age;//获取age long long hp=r.hp;//获取hp long long mp=r.mp;//获取mp string str2=r.encode2string();//生成json字符串
你看这样用起来十分简单了? 但是如果你的通讯协议有很多要转换的json数据,以及每个json里面的数据非常复杂,你要写的代码是会非常多的,所以你需要一款工具,帮你自动的从一个json文件(协议格式定义文件)转换成一个c++代码文件
这就有了我做的json2jsoncpp
你只需要写好json文件,这个工具就可以生成一个h文件来了
工具使用比较简单,就是
json2jsoncpp.exe yourjson [yourh]
这样就能生成出来你要的h文件了
json的定义格式也很简单,首先它就是个标准的json格式文件
类似这样:
{ //如果你需要给你生成的h文件包含一个命名空间,只需要写入: "namespace":"KAKA", //先给你的json数据包格式起个名字叫做rpc1 "rpc1" : { "age":16,//年龄 "hp":99,//血 "mp":88//魔法 }, //第二个数据格式 "rpc2" : { "box":16 } }
按照这格式你就可以生成你想要的h文件了
类里面包含几个方法:
decode() //解码json数据
encode() //编码成Json::Value变量
encode2string() //编码成string
reset() //重置变量恢复到默认值
附上 win/mac/linux 的应用下载地址:http://pan.baidu.com/share/link?shareid=308752&uk=3711199009
先写到这里,下回再说说哦json2jsoncpp的一些高级应用
附:我叫杨卡,目前在广州一家做视频监控平台的公司担任开发工程师/主管,在工作与学习的过程中有一些心得体会在这里与大家分享分享,与大家一起共同学习与进步,欢迎大家多多关注。
我的hotmail.com信箱是:vanishs