由于工作上有一个通过AE访问arcserver服务的需求,就做了一些这方面的工作。访问地图的方式,已经有很多人写过了,我就不在这里赘述了。我这里主要内容是查询方面的功能,通过访问rest接口,返回json串,然后再解析json。
这里涉及到两个主要的知识点
1,http协议方面内容
2,json解析
http可以通过CInternetSession,CHttpConnection,CHttpFile等类来操作,还是比较方便的。
json可以通过三方库来完成,jsoncpp和boost是比较常见的两个,我这里采用了jsoncpp。boost的功能比较强悍,还可以解析xml,ini等,不过也有一些已知的bug。jsoncpp我这里使用没发现bug,不过有人反映这个效率不是很高。
jsoncpp(jsoncpp-src-0.5.0)大家可以通过官网去下载,我是用vs2008编译的,开始编译遇到很多莫名奇妙的问题,其实只要在编译前制定编码方式为unicode,release模式关闭优化,编译就没问题。
这里贴几段主要的代码,最后提供测试代码给大家下载
通过post方式查询,这个查询里面要注意转码,从unicode转换为utf-8。
//strServer 服务器地址 //strObjectName 比如/ArcGIS/rest/services/yongdiguihuazongtuceng/MapServer/1/query? 包含了图层名,类型,索引 //nPort 指定了端口,默认为80 void MyHttp::MyHttpPost( CString strServer,CString strObjectName,CString strQuery,int nPort,string &json ) { json = ""; CInternetSession session(NULL,1,INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0); CHttpConnection* pConnection=NULL; CHttpFile* pFile=NULL; INTERNET_PORT port=nPort; session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 10*1000); pConnection = session.GetHttpConnection(strServer,port); pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,strObjectName); CString strHeaders =_T("Content-Type: application/x-www-form-urlencoded\r\n";); char cQuery[1024]; memset(cQuery,0,sizeof(cQuery)); CodeConvert::UnicodeToUTF8(strQuery,cQuery); string data = ""; data = cQuery; try { if ( pFile->SendRequest(strHeaders, (LPVOID *)data.c_str(), data.length()) ) { DWORD StatusCode; pFile->QueryInfoStatusCode(StatusCode); if ( HTTP_STATUS_OK == StatusCode ) { CString strHtml = _T(""); CString myData; long i =0; while ( pFile->ReadString ( myData ) ) { i++; strHtml += myData; } CodeConvert::Utf8ToGBK(strHtml); //USES_CONVERSION; //调用函数,T2A和W2A均支持ATL和MFC中的字符转换 //这种方法,在strhtml足够大的时候,会引发异常,查询了一下,是栈空间不足, //不过按照提示的方法,没有修复错误,所以使用了另一种方式来实现 //char * pHtml = W2A(strHtml); //json = pHtml; // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString (strHtml); // construct a std::string using the LPCSTR input std::string strStd (pszConvertedAnsiString); json = strStd; } } } catch(...) { } session.Close(); if (NULL != pFile) { delete pFile; pFile = NULL; } if (NULL != pConnection) { delete pConnection; pConnection = NULL; }
使用jsoncpp,先包含所需的内容
#include "json/json.h" #ifdef _DEBUG #pragma comment(lib, "json/json_vc90_libmtd.lib") #else #pragma comment(lib, "json/json_vc90_libmt.lib") #endif using namespace Json;
解析json,这里其实了解了json的格式就不难,我这里只是读,涉及到的json::value,注意其各种格式解析就好了
BOOL MyJson::GetValue( string json,CString strKey,CString &strArr ) { if (json.empty()) { return FALSE; } strArr = _T(""); vector<CString> arr; USES_CONVERSION; char* s_char=W2A(strKey); Reader reader; Value value; CString str; if (reader.parse(json, value)) { Value result = value["features"]; ValueType vType = result.type(); if (nullValue == vType) { return FALSE; } Value::UInt nSize = result.size(); for (Value::UInt i=0; i<nSize; i++) { Value name = result[i]["attributes"][s_char]; vType = name.type(); if (nullValue == vType) { return FALSE; } CString s = A2T(name.asCString()); BOOL bAdd = FALSE; vector<CString>::iterator iter = arr.begin(); while(iter != arr.end()) { if (s.CompareNoCase(*iter) == 0) { bAdd = TRUE; break; } iter ++; } if (TRUE != bAdd) { arr.push_back(s); } } } if (arr.size() < 1) { return FALSE; } strArr = arr[0]; for(vector<CString>::size_type i=1; i< arr.size(); i++) { strArr +=_T(","); strArr += arr[i]; } return TRUE; }
示例里面包含了put和get方法的实现,json数组的解析
boost库的方式操作json,参见另一篇文章