c/c++使用cJson解析未知內容的json字串
關於json我這裡就不做綴飾,這裡給出連結百度百科json
我這裡只介紹下json中的符號格式
① { } : 雙括號表示一個json物件。例如:{"name":"ljl"},這代表一個name為ljl的物件
②[ ] : 中括號表示陣列。例如:[{"name","ljl"},{"memory","ljx"}],表示包含兩個物件的陣列
③ : :冒號表示後者是前者的值。比如我上面的{"name":"ljl"},ljl是name的值
④" " :雙引號內是屬性或值。例如{"date","18-09-28"},屬性是date,它的值是18-09-28
⑤, :逗號表示間隔,常用於兩個物件之間。如[{"name","ljl"},{"memory","ljx"}]
json在java中使用比較容易,一般在c/c++中不使用該格式,但有時專案會涉及到前端用c/c++去編寫而後端用Java編寫,這兩者間通訊時一般都選用Json格式
c/c++中能夠解析、建立Json字串的工具(或者說方法)不多,目前筆者只找到cJson跟Jsoncpp兩種簡單方法。其中cJson最為方便,這裡使用cJson做為解析、建立Json的工具
如果沒有cJson,本文給出下載連結cJson下載
將cJson.h和cJson.c新增到專案幷包含路徑即可使用(注意:.c檔案必須新增至專案,否則不會編譯)
test.c檔案為官方演示測試檔案,裡面有一些函式的簡單用法
下面展示下如何解析已知結構的簡單Json字串
#include <iostream> #include "cJSON.h" #include <string> #include <Windows.h> #include <map> using namespace std; int main() { string json_string = "{\"ResCode\":\"000\",\"ResDesc\":\"業務受理成功\",\"ServiceResMsg\":\"這是XML格式字串\"}"; //JSON字串到cJSON格式 cJSON* cjson1 = cJSON_Parse(json_string.c_str()); //判斷cJSON_Parse函式返回值確定是否打包成功 if(cjson1 == NULL) { printf("json pack into cjson error..."); } else { //打包成功呼叫cJSON_Print列印輸出 cJSON_Print(cjson1); // 將json形式列印成正常字串形式 } //獲取欄位值 //cJSON_GetObjectltem返回的是一個cJSON結構體所以我們可以通過函式返回結構體的方式選擇返回型別! string _1_string = cJSON_GetObjectItem(cjson1,"ResCode")->valuestring; string _2_string = cJSON_GetObjectItem(cjson1,"ResDesc")->valuestring; string _3_string = cJSON_GetObjectItem(cjson1,"ServiceResMsg")->valuestring; cout << _1_string << endl; cout << _2_string << endl; cout << _3_string << endl; //delete cjson cJSON_Delete(cjson1); return 0; }
程式碼中
string _1_string = cJSON_GetObjectItem(cjson1,"ResCode")->valuestring;
string _2_string = cJSON_GetObjectItem(cjson1,"ResDesc")->valuestring;
string _3_string = cJSON_GetObjectItem(cjson1,"ServiceResMsg")->valuestring;
通過呼叫cJSON_GetObjectItem函式將已知結構,比如ResCode,ResDesc,ServiceResMsg三個節點的值讀出來
關於複雜的Json字串解析,諸如包含陣列的,可以去其他csdn檢視,有些部落格寫的還是很到位的,我這裡主要講解析未知內容的Json字串
筆者研究了下cJson.c跟cJson.h檔案,貌似沒有發現可以直接解析未知Json字串的方法,但筆者在cJson.h中找到了官方定義的結構體
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
筆者稍微研究了下cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)函式
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)
{
cJSON *c=object->child;
while (c && cJSON_strcasecmp(c->string,string))
c=c->next;
return c;
}
該函式內部實現的是通過遍歷cJson的物件中struct cJSON *child中的struct cJSON *next,*prev來達成遍歷Json字串的目的
下面我們就通過這種方法自己寫一個介面函式,實現解析未知結構、內容的Json字串
#include <iostream>
#include "cJSON.h"
#include <string>
#include <Windows.h>
#include <map>
using namespace std;
map<string,string> MapAnalysisJSON(string ResMessage)
{
map<string,string> mapResMessage;
cJSON* cjson = cJSON_Parse(ResMessage.c_str());
if(cjson == NULL)
{
printf("json pack into cjson error...");
}
else
{
cJSON_Print(cjson);
}
cJSON * c = cjson->child;
while (c)
{
mapResMessage.insert(pair<string,string>(c->string,c->valuestring));
c = c->next;
}
c = NULL;
return mapResMessage;
}
int main()
{
string json_string = "{\"ResCode\":\"000\",\"ResDesc\":\"業務受理成功\",\"ServiceResMsg\":\"這是XML格式字串\"}";
map<string,string> recmap;
recmap = MapAnalysisJSON(json_string);
if (recmap.size() == 0)
{
cout << "recmap is empty!";
}
for (map<string,string>::iterator iter = recmap.begin();iter != recmap.end();iter++)
{
cout << iter->first << " " << iter->second << endl;
}
return 0;
}
我這裡將未知Json字串解析成map物件
map跟Json的理念有點相似即一個鍵對應一個值,當然你也可以將Json解析成你想要的任何格式