您的位置:首页 > 编程语言 > C语言/C++

C++处理JSON数据和在face++ 调用中的使用

2016-03-28 17:29 393 查看
使用C++处理JSON数据交换格式
一、摘要
JSON的全称为:JavaScriptObjectNotation,顾名思义,JSON是用于标记Javascript对象的,JSON官方的解释为:JSON是一种轻量级的数据传输格式。本文并不详细介绍JSON本身的细节,旨在讨论如何使用C++语言来处理JSON。关于JSON更具体的信息,可参见JSON官网:http://www.json.org。http://json.org/json-zh.html
二、本文选择处理JSON的C++库
本文选择一个第三方库jsoncpp来解析JSON。jsoncpp是比较出名的C++JSON解析库。在JSON官网也是首推的。下载地址为:http://sourceforge.net/projects/jsoncpp。本文使用的jsoncpp版本为:0.5.0。
三、jsoncpp在Windows下的编译
方法一:使用Jsoncpp生成的lib文件
解压上面下载的Jsoncpp文件,在jsoncpp-src-0.5.0/makefiles/vs71目录里找到jsoncpp.sln,用VS2008版本编译,默认生成静态链接库。在工程中引用,只需要包含include/json下的头文件及生成的.lib文件即可。
如何包含lib文件:在.cpp文件中#pragmacomment(lib."json_vc71_libmt.lib"),
在工程属性中Linker下Input中AdditionalDependencies写入lib文件名字(Release下为json_vc71_libmt.lib,Debug为json_vc71_libmtd.lib)
注意:Jsoncpp的lib工程编译选项要和VS工程中的编译选项保持一致。如lib文件工程编译选项为MT(或MTd),VS工程中也要选择MT(或MTd),否则会出现编译错误问题,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中AdditionalIncludeDirectories包含头文件目录.\jsoncpp-src-0.5.0\include。在使用的cpp文件中包含json头文件即可,如:#include"json/json.h"。将json_reader.cpp、json_value.cpp和json_writer.cpp三个文件的PrecompiledHeader属性设置为NotUsingPrecompiledHeaders,否则编译会出现错误。jsoncpp使用详解jsoncpp主要包含三种类型的class:Value、Reader、Writer。jsoncpp中所有对象、类名都在namespaceJson中,包含json.h即可。Json::Value只能处理ANSI类型的字符串,如果C++程序是用Unicode编码的,最好加一个Adapt类来适配。
本实验采用方法二,这样方便调试,同时也方便学习该开源库的代码。本代码不为商用,所以以学习为主。
四\需要解析的数据,face++调动返回json数据,数据个数如下:
{"face":[{"attribute":{"age":{"range":5,"value":23},"gender":{"confidence":99.9999,"value":"Female"},"glass":{"confidence":99.945,"value":"None"},"pose":{"pitch_angle":{"value":17},"roll_angle":{"value":0.735735},"yaw_angle":{"value":-2}},"race":{"confidence":99.6121,"value":"Asian"},"smiling":{"value":4.86501}},"face_id":"17233b4b1b51ac91e391e5afe130eb78","position":{"center":{"x":49.4,"y":37.6},"eye_left":{"x":43.3692,"y":30.8192},"eye_right":{"x":56.5606,"y":30.9886},"height":26.8,"mouth_left":{"x":46.1326,"y":44.9468},"mouth_right":{"x":54.2592,"y":44.6282},"nose":{"x":49.9404,"y":38.8484},"width":26.8},"tag":""}],"img_height":500,"img_id":"22fd9efc64c87e00224c33dd8718eec7","img_width":500,"session_id":"38047ad0f0b34c7e8c6efb6ba39ed355","url":"http://www.faceplusplus.com.cn/wp-content/themes/faceplusplus/assets/img/demo/1.jpg?v=4"}
五、遇到问题,曾经尝试多次,找了很多博客都是不能解决问题,
仔细观察后,发现有[],这个不能忽视。http://blog.163.com/pei_hua100/blog/static/80569759201333114010800/通过这个博客启发。发现[]为里面的数据。所以更改代码如下。
<spanstyle="color:#333333;">Json::Valuedetect;Json::Valueface;if(!DetectResult1.parse(DetectResult,detect)){return-1;}intface_size=detect["face"].size();//遍历face个数for(inti=0;i<face_size;i++)</span><spanstyle="color:#ff0000;">这里很关键,学会使用该方法。</span><spanstyle="color:#333333;">{Json::Valueattribute;attribute=detect["face"][i]["attribute"];intattribute_size=attribute.size();intage=attribute["age"]["value"].asInt();stringgender=attribute["gender"]["value"].asString();intsmiling=attribute["smiling"]["value"].asInt();stringrace=attribute["race"]["value"].asString();}for(inti=0;i<face_size;i++){Json::Valueposition;position=detect["face"][i]["position"];intcenterX=position["center"]["x"].asInt();intcenterY=position["center"]["y"].asInt();inteye_leftx=position["eye_left"]["x"].asInt();inteye_lefty=position["eye_left"]["y"].asInt();inteye_rightx=position["eye_right"]["x"].asInt();inteye_righty=position["eye_right"]["y"].asInt();intheight=position["height"].asInt();cout<<"centerX"<<centerX<<"centerY"<<centerY<<endl;intmouth_leftx=position["mouth_left"]["x"].asInt();intmouth_lefty=position["mouth_left"]["y"].asInt();intmouth_rightx=position["mouth_right"]["x"].asInt();intmouth_righty=position["mouth_right"]["y"].asInt();intnosex=position["nose"]["x"].asInt();intnosey=position["nose"]["y"].asInt();intwidth=position["width"].asInt();}intimg_height=detect["img_height"].asInt();cout<<"img_height"<<img_height<<endl;intimg_width=face["img_width"].asInt();</span>
通过这个方式,发现curl返回的代码里面有\n换行符,想办法去掉他。
本实验的实现方式如下:
//去掉返回值中的\n换行符string::iteratorit;for(it=HTTPRESULT.begin();it!=HTTPRESULT.end();++it){if(*it=='\n'){//	*it='\\r\\n';HTTPRESULT.erase(it);}}
本次实验所有代码如下:
//face++.cpp:定义控制台应用程序的入口点。//#include"stdafx.h"#include<string>#include<iostream>usingnamespacestd;#include"HttpClient.h"#include"curl/curl.h"#include"curl/easy.h"std::stringstrResult;#include<opencv2\core\core.hpp>#include<opencv2\highgui\highgui.hpp>#include"json/json.h"usingnamespacecv;//#pragmacomment(lib,"libcurl.lib")std::stringHTTPRESULT;constchar*detectResult;voidWrite_data(void*buffer,size_tsize,size_tnmemb,void*user_p){cout<<"(constchar*)buffer"<<(constchar*)buffer<<endl;HTTPRESULT+=(constchar*)buffer;detectResult=(constchar*)buffer;}int_tmain(intargc,_TCHAR*argv[]){CURL*curl=curl_easy_init();CURLcoderes=curl_global_init(CURL_GLOBAL_WIN32);structcurl_httppost*formpost=NULL;structcurl_httppost*lastptr=NULL;//structcurl_slist*headerlist=NULL;//staticconstcharbuf[]="Expect:";curl_formadd(&formpost,&lastptr,CURLFORM_COPYNAME,"api_key",CURLFORM_COPYCONTENTS,"d45344602f6ffd77baeab05b99fb7730",CURLFORM_END);curl_formadd(&formpost,&lastptr,CURLFORM_COPYNAME,"api_secret",CURLFORM_COPYCONTENTS,"jKb9XJ_GQ5cKs0QOk6Cj1HordHFBWrgL",CURLFORM_END);char*file_data=NULL;longfile_size=0;stringimageName="d:\\mqx.jpg";FILE*fp=fopen("d:\\mqx.jpg","rb");if(fp){fseek(fp,0,SEEK_END);file_size=ftell(fp);fseek(fp,0,SEEK_SET);file_data=newchar[file_size+1];fread(file_data,1,file_size,fp);cout<<file_data<<endl;fclose(fp);}curl_formadd(&formpost,&lastptr,CURLFORM_COPYNAME,"img",CURLFORM_BUFFER,"test.jpg",CURLFORM_BUFFERPTR,file_data,CURLFORM_BUFFERLENGTH,file_size,CURLFORM_CONTENTTYPE,"image/jpeg",CURLFORM_END);if(curl){//whatURLthatreceivesthisPOSTcurl_easy_setopt(curl,CURLOPT_URL,"http://apicn.faceplusplus.com/v2/detection/detect");curl_easy_setopt(curl,CURLOPT_VERBOSE,0);curl_easy_setopt(curl,CURLOPT_HTTPPOST,formpost);curl_easy_setopt(curl,CURLOPT_WRITEDATA,&HTTPRESULT);curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,Write_data);cout<<"CURLOPT_WRITEFUNCTION"<<CURLOPT_WRITEFUNCTION<<endl;charerror[1024];curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,error);res=curl_easy_perform(curl);if(res!=CURLE_OK)cout<<endl<<error<<endl;}curl_easy_cleanup(curl);curl_formfree(formpost);cout<<endl<<HTTPRESULT<<endl;//	cout<<endl<<"测试结果如下"<<endl;//	cout<<endl<<"年龄:"<<HTTPRESULT.find("value")<<endl;//	cout<<endl<<"年龄:"<<HTTPRESULT.substr(HTTPRESULT.find("age",0))<<endl;//	cout<<endl<<"年龄:"<<HTTPRESULT.substr(HTTPRESULT.find("gender",0))<<endl;//	cout<<endl<<"年龄:"<<HTTPRESULT.substr(HTTPRESULT.find("race",0))<<endl;//	cout<<endl<<"年龄:"<<HTTPRESULT.substr(HTTPRESULT.find("smiling",0))<<endl;//得到年龄性别等。intagePos=HTTPRESULT.find("age",0);stringage=HTTPRESULT.substr(agePos+70,2);intgenderPos=HTTPRESULT.find("gender",0);stringgender=HTTPRESULT.substr(genderPos+84,6);intracePos=HTTPRESULT.find("race",0);stringrace=HTTPRESULT.substr(racePos+83,5);intsmilingPos=HTTPRESULT.find("smiling",0);stringsmiling=HTTPRESULT.substr(smilingPos+41,5);//end结束/*//读入图像Matimg=imread(imageName,CV_LOAD_IMAGE_COLOR);//如果读入图像失败if(img.empty()){cout<<"Couldnotopenorfindtheimage!"<<endl;return-1;}//创建窗口namedWindow("face",CV_WINDOW_AUTOSIZE);//显示图像imshow("face",img);//等待按键,按键盘任意键返回waitKey(-1);//	while(HTTPRESULT!="")//	{//		agePos[numage]=HTTPRESULT.find("value");//		HTTPRESULT//	}//	intagePos=HTTPRESULT.find("value");if(file_data!=NULL)delete[]file_data;*///HTTPRESULT=HTTPRESULT.replace(/\\n/g,"\\n");//去掉返回值中的\n换行符string::iteratorit;for(it=HTTPRESULT.begin();it!=HTTPRESULT.end();++it){if(*it=='\n'){//	*it='\\r\\n';HTTPRESULT.erase(it);}}constchar*DetectResult=HTTPRESULT.c_str();Json::ReaderDetectResult1;Json::Valuedetect;Json::Valueface;if(!DetectResult1.parse(DetectResult,detect)){return-1;}intface_size=detect["face"].size();//遍历face个数for(inti=0;i<face_size;i++){Json::Valueattribute;attribute=detect["face"][i]["attribute"];intattribute_size=attribute.size();intage=attribute["age"]["value"].asInt();stringgender=attribute["gender"]["value"].asString();intsmiling=attribute["smiling"]["value"].asInt();stringrace=attribute["race"]["value"].asString();}for(inti=0;i<face_size;i++){Json::Valueposition;position=detect["face"][i]["position"];intcenterX=position["center"]["x"].asInt();intcenterY=position["center"]["y"].asInt();inteye_leftx=position["eye_left"]["x"].asInt();inteye_lefty=position["eye_left"]["y"].asInt();inteye_rightx=position["eye_right"]["x"].asInt();inteye_righty=position["eye_right"]["y"].asInt();intheight=position["height"].asInt();cout<<"centerX"<<centerX<<"centerY"<<centerY<<endl;intmouth_leftx=position["mouth_left"]["x"].asInt();intmouth_lefty=position["mouth_left"]["y"].asInt();intmouth_rightx=position["mouth_right"]["x"].asInt();intmouth_righty=position["mouth_right"]["y"].asInt();intnosex=position["nose"]["x"].asInt();intnosey=position["nose"]["y"].asInt();intwidth=position["width"].asInt();}intimg_height=detect["img_height"].asInt();cout<<"img_height"<<img_height<<endl;intimg_width=face["img_width"].asInt();system("pause");return0;}
下面是从网上找的代码示例:1.从字符串解析jsonconstchar*str="{\"uploadid\":\"UP000000\",\"code\":100,\"msg\":\"\",\"files\":\"\"}";Json::Readerreader;Json::Valueroot;if(reader.parse(str,root))//reader将Json字符串解析到root,root将包含Json里所有子元素{std::stringupload_id=root["uploadid"].asString();//访问节点,upload_id="UP000000"intcode=root["code"].asInt();//访问节点,code=100}2.从文件解析jsonintReadJsonFromFile(constchar*filename){Json::Readerreader;//解析json用Json::ReaderJson::Valueroot;//Json::Value是一种很重要的类型,可以代表任意类型。如int,string,object,arraystd::ifstreamis;is.open(filename,std::ios::binary);if(reader.parse(is,root,FALSE)){std::stringcode;if(!root["files"].isNull())//访问节点,Accessanobjectvaluebyname,createanullmemberifitdoesnotexist.code=root["uploadid"].asString();code=root.get("uploadid","null").asString();//访问节点,Returnthemembernamedkeyifitexist,defaultValueotherwise.intfile_size=root["files"].size();//得到"files"的数组个数for(inti=0;i<file_size;++i)//遍历数组{Json::Valueval_image=root["files"][i]["images"];intimage_size=val_image.size();for(intj=0;j<image_size;++j){std::stringtype=val_image[j]["type"].asString();std::stringurl=val_image[j]["url"].asString();printf("type:%s,url:%s\n",type.c_str(),url.c_str());}}}is.close();return0;}3.向文件中插入jsonvoidWriteJsonData(constchar*filename){Json::Readerreader;Json::Valueroot;//Json::Value是一种很重要的类型,可以代表任意类型。如int,string,object,arraystd::ifstreamis;is.open(filename,std::ios::binary);if(reader.parse(is,root)){Json::ValuearrayObj;//构建对象Json::Valuenew_item,new_item1;new_item["date"]="2011-11-11";new_item1["time"]="11:11:11";arrayObj.append(new_item);//插入数组成员arrayObj.append(new_item1);//插入数组成员intfile_size=root["files"].size();for(inti=0;i<file_size;++i)root["files"][i]["exifs"]=arrayObj;//插入原json中std::stringout=root.toStyledString();//输出无格式json字符串Json::FastWriterwriter;std::stringstrWrite=writer.write(root);std::ofstreamofs;ofs.open("test_write.json");ofs<<strWrite;ofs.close();}is.close();}
要使用第三方源码库,第一步少不了的就是编译,将源码文件编译成我们方便使用的动态链接库、静态链接库或者静态导入库[1]。
jsconcpp进行JSON解析的源码文件分布在include/json、src/lib_json下。其实jsoncpp源码并不多,为了方便产品管理,此处没必要将其编译为动态链接库或者静态导入库,所以我们选择使用静态链接库[2]。
jsoncpp已经处理的很完善了,所有编译选项都已经配置好,打开makefiles/vs71/jsoncpp.sln便可以开始编译(默认是使用VS2003编译器的,打开时直接按照VS2005提示转换即可)。
四、jsoncpp使用详解
jsoncpp主要包含三种类型的class:Value、Reader、Writer。jsoncpp中所有对象、类名都在namespaceJson中,包含json.h即可。
Json::Value只能处理ANSI类型的字符串,如果C++程序是用Unicode编码的,最好加一个Adapt类来适配。
1、Value
Json::Value是jsoncpp中最基本、最重要的类,用于表示各种类型的对象,jsoncpp支持的对象类型可见Json::ValueType枚举值。
可如下是用Json::Value类:
Json::Valuejson_temp;//临时对象,供如下代码使用
json_temp["name"]=Json::Value("huchao");
json_temp["age"]=Json::Value(26);
Json::Valueroot;//表示整个json对象
root["key_string"]=Json::Value("value_string");//新建一个Key(名为:key_string),赋予字符串值:"value_string"。
root["key_number"]=Json::Value(12345);//新建一个Key(名为:key_number),赋予数值:12345。
root["key_boolean"]=Json::Value(false);//新建一个Key(名为:key_boolean),赋予bool值:false。
root["key_double"]=Json::Value(12.345);//新建一个Key(名为:key_double),赋予double值:12.345。
root["key_object"]=Json_temp;//新建一个Key(名为:key_object),赋予json::Value对象值。
root["key_array"].append("array_string");//新建一个Key(名为:key_array),类型为数组,对第一个元素赋值为字符串:"array_string"。
root["key_array"].append(1234);//为数组key_array赋值,对第二个元素赋值为:1234。
Json::ValueTypetype=root.type();//获得root的类型,此处为objectValue类型。
注:跟C++不同,JavaScript数组可以为任意类型的值,所以jsoncpp也可以。
如上几个用法已经可以满足绝大部分json应用了,当然jsoncpp还有一些其他同能,比如说设置注释、比较json大小、交换json对象等,都很容易使用,大家自己尝试吧。
2、Writer
如上说了Json::Value的使用方式,现在到了该查看刚才赋值内容的时候了,查看json内容,使用Writer类即可。
Jsoncpp的Json::Writer类是一个纯虚类,并不能直接使用。在此我们使用Json::Writer的子类:Json::FastWriter、Json::StyledWriter、Json::StyledStreamWriter。
顾名思义,用Json::FastWriter来处理json应该是最快的,下面我们来试试。
Json::FastWriterfast_writer;
std::cout<<fast_writer.write(root)<<std::endl;
输出结果为:
{"key_array":["array_string",1234],"key_boolean":false,"key_double":12.3450,"key_number":12345,"key_object":{"age":26,"name":"huchao"},"key_string":"value_string"}
再次顾名思义,用Json::StyledWriter是格式化后的json,下面我们来看看Json::StyledWriter是怎样格式化的。
Json::StyledWriterstyled_writer;
std::cout<<styled_writer.write(root)<<std::endl;
输出结果为:
{"key_array":["array_string",1234],"key_boolean":false,"key_double":12.3450,"key_number":12345,"key_object":{"age":26,"name":"huchao"},"key_string":"value_string"}
3、Reader
Json::Reader是用于读取的,说的确切点,是用于将字符串转换为Json::Value对象的,下面我们来看个简单的例子。
Json::Readerreader;
json::Valuejson_object;
constchar*json_document="{\"age\":26,\"name\":\"huchao\"}";
if(!reader.parse(json_document,json_object))
return0;
std::cout<<json_object["name"]<<std::endl;
std::cout<<json_object["age"]<<std::endl;
输出结果为:
"huchao"
26
可见,上述代码已经解析出了json字符串。
--------------------------------------
[1]:使用第三方源码最简单的方法是直接将文件加入工程,但这样不利于源码、软件产品管理,对于一般软件开发来说,不建议使用。
[2]:如果真需要编译成动态链接库、静态导入库的话,可以使用VS新建一个工程属性,然后在Project-->Properties中进行相应的设置即可。
转载地址:http://hi.baidu.com/awz_tiger/blog/item/d165970b4ca967fc36d122a4.html
另一个比较有用的地址为:/article/1698498.html
参考资料:'target='_blank'>http://blog.csdn.net/chen19870707/article/details/39646173[/code]
http://www.cppblog.com/wanghaiguang/archive/2013/12/26/205020.html
http://bbs.csdn.net/topics/370006412

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: