1. 程式人生 > >c/c++使用cJson解析未知內容的json字串

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解析成你想要的任何格式