使用json-c 體會

轉自:https://blog.csdn.net/qimi123456/article/details/80426474

json-c 庫中是在嵌入式開發中常用的庫。因爲很多地方都以json數據數據交互協議, 尤其嵌入式web數據交互時通常會用到json格式, 因此如果需要在產品端進行json數據解析 , json-c 是一個比較不錯的選擇。本次我主要是對json數據的解析 , 主要是整型 , 字符串 和數據 , 進行解析。一.將json格式的數據轉化爲一個json對象 :jsonobj那麼首先需要的就是有一個可以被解析的json對象。因爲從web來的的數據一般是字符串也可以純文本,而json-c對這兩種都支持。先說json格式的字符串轉成json對象:

json_object* json_tokener_parse(const char *str);
 

或者以具有json格式文本內容的文本文件轉化爲json對象:

json_object* json_object_from_file(const char *filename);

這兩種方式都可以輕鬆將json格式的數據轉化爲json對象。並進一步進行解析。

二.對json對象進行解析

這個解析主要分兩步走

    第一步:根據鍵名,從json對象中獲取對應數據的json對象

    第二步: 根據數據類型,將數據對應的json對象轉化爲對應類型的數據

 主要接口:

json_bool json_object_object_get_ex(struct json_object* obj, const char *key, struct json_object **value);
這個是一個增強的接口, 參數說明:    obj:源json對象 , 即需要從obj這個json對象取數據    key: 需要取數據的鍵名    value: 用於存放獲取的對應數據的json對象,注意這裏一定傳入的是二級指針。不用傳入實體將對應的整型數據json數據轉成對應的整型數據
int32_t json_object_get_int(struct json_object *obj);

將對應的json字符串轉換爲字符串數據

extern const char* json_object_get_string(struct json_object *obj);
提取json數組中元素,當然這個元素也是一個json對象

json_object* json_object_array_get_idx(struct json_object *obj , int idx);

參數說明:

    obj:json數據對象

    idx:數據元素的腳標索引

 

當然還有其他的接口就不說了, 目前就對數據進行解析, 沒有對數據封裝成json數據

但是這個json數據解析需要注意釋放內存

以上接口產生的json對象 , 都需分別用

json_object_put(struct json_object *obj);

對內存進行釋放

最後貼一個測試代碼


#include <stdio.h>

#include <Alooper/Errors.h>

#include <linux/types.h>

#include <jsonc/json.h>

 

typedef long long off64_t;

 

#include <ghttp/ghttp.h>

/**是否強制退出http處理**/

static int mCancelHttp = 0;

 

char buffer[4096];

 

 

/***專輯列表數據***/

typedef struct speciallist_s{

//	int keyId;

	char id[10];

	char name[128];

	int type;

	int count;

}speciallist_t;

 

char *jsonstr = "{\"data\":[{\"id\":\"100101\",\"name\":\"小學語文一年級上(人教版)\",\"type\":0,\"count\":20},{\"id\":\"100102\",\"name\":\"小學語文一年級下(人教版)\",\"type\":1,\"count\":37},{\"id\":\"100103\",\"name\":\"小學語文二年級上(人教版)\",\"type\":1,\"count\":40},{\"id\":\"100104\",\"name\":\"小學語文二年級下(人教版)\",\"type\":1,\"count\":41},{\"id\":\"100105\",\"name\":\"小學語文三年級上(人教版)\",\"type\":1,\"count\":35},{\"id\":\"100106\",\"name\":\"小學語文三年級下(人教版)\",\"type\":1,\"count\":32},{\"id\":\"100107\",\"name\":\"小學語文四年級上(人教版)\",\"type\":1,\"count\":32},{\"id\":\"100108\",\"name\":\"小學語文四年級下(人教版)\",\"type\":1,\"count\":32},{\"id\":\"100109\",\"name\":\"小學語文五年級上(人教版)\",\"type\":1,\"count\":36},{\"id\":\"100110\",\"name\":\"小學語文五年級下(人教版)\",\"type\":1,\"count\":30},{\"id\":\"100111\",\"name\":\"小學語文六年級上(人教版)\",\"type\":1,\"count\":33},{\"id\":\"100112\",\"name\":\"小學語文六年級下(人教版)\",\"type\":1,\"count\":32},{\"id\":\"100201\",\"name\":\"小學英語一年級上(人教版)\",\"type\":1,\"count\":38},{\"id\":\"100202\",\"name\":\"小學英語一年級下(人教版)\",\"type\":1,\"count\":38},{\"id\":\"100203\",\"name\":\"小學英語二年級上(人教版)\",\"type\":1,\"count\":38},{\"id\":\"100204\",\"name\":\"小學英語二年級下(人教版)\",\"type\":1,\"count\":38},{\"id\":\"100205\",\"name\":\"小學英語三年級上(人教版)\",\"type\":1,\"count\":60},{\"id\":\"100206\",\"name\":\"小學英語三年級下(人教版)\",\"type\":1,\"count\":60}],\"total\":18,\"flag\":99,\"result\":0}";

 

 

 

/*********

 	數據解析

 ***********/

int dedata(char *databuf)

{

	int i = 0;

	int total  = 0;

	int flag = 0;

	int result = 0;

	int ret = -1;

	speciallist_t listdata[20];

	if(NULL == databuf)

	{

		printf("the databuf is NULL ...\n");

	}

	json_object *jsonobj = NULL;

	json_object *tmpjson = NULL;

	json_object *datajson = NULL;

	json_object *listjson = NULL;

	printf("databuf :[%s], size:[%d]\n",databuf , strlen(databuf));

	//jsonobj = json_object_new_string_len(databuf , strlen(databuf));

//	jsonobj = json_object_new_string(jsonstr);

	jsonobj = json_tokener_parse(databuf);

	if(NULL == jsonobj)

	{

		printf("the jsonobj is error \n");

	}

//	printf("json:%s",json_object_to_json_string(jsonobj));

	ret =json_object_object_get_ex(jsonobj , "total" , &tmpjson);

	if(!ret)

	{

		printf("get jsondata error ...\n");

	}

		

	if(NULL == tmpjson)

	{

		printf("the tmpjson : [%s]\n",json_object_to_json_string(tmpjson));

	}

	/**獲取total***/

	total = json_object_get_int(tmpjson);

	json_object_put(tmpjson);

//	tmpjson = NULL;

	/***獲取flag***/

	json_object_object_get_ex(jsonobj , "flag" , &tmpjson);

	flag = json_object_get_int(tmpjson);

	json_object_put(tmpjson);

	/***獲取result***/

	json_object_object_get_ex(jsonobj , "result" , &tmpjson);

	result = json_object_get_int(tmpjson);

	json_object_put(tmpjson);

	

	/***獲取data***/

	json_object_object_get_ex(jsonobj , "data" , &tmpjson);

	for(i = 0 ; i < total ; i++)

	{

		datajson = json_object_array_get_idx(tmpjson , i);

		json_object_object_get_ex(datajson , "id" , &listjson);

		strcpy(listdata[i].id , json_object_get_string(listjson));

 

		json_object_object_get_ex(datajson , "name" , &listjson);

		strcpy(listdata[i].name , json_object_get_string(listjson));

 

		json_object_object_get_ex(datajson , "type" , &listjson);

		listdata[i].type = json_object_get_int(listjson);

 

		json_object_object_get_ex(datajson , "count" , &listjson);

		listdata[i].count = json_object_get_int(listjson);

		

		json_object_put(listjson);

	}

	

	json_object_put(tmpjson);

	

	/***釋放json對象***/

	json_object_put(jsonobj);

	printf("------------the data -----------------\n");

	printf("{\n\t\"data\":\n\t\t[\n");

	for(i = 0 ; i < total ; i++)

	{

		printf("\t\t\t\{\"id\":\"%s\",\"name\":\"%s\",\"type\":%d,\"count\":%d\n",listdata[i].id , listdata[i].name,listdata[i].type,listdata[i].count);

	}

	printf("\t\t],\n\t\"total\":%d,\n\t\"flag\":%d,\n\t\"result\":%d\n}",total,flag , result);

 

	return 0;

}

 

 

/***從外部線程中斷http請求 , 避免網絡差時卡在http請求中***/

void http_abort(void)

{

	mCancelHttp = 1;

}

 

int http_interrupt(void *arg)

{

	static i = 0;

	printf("http is been interrupt :%d \n",i++);

	return *(int *)arg;

}

 

 

/*******

 	獲取重定向url

 *******/

static char *_get_redirect_url(char *url , ghttp_request *req)

{

	const char *newUri = ghttp_get_resp_header(req , http_hdr_Location);

	if(NULL == newUri)

	{

		return NULL;

	}

 

	if(newUri[0] == '/')

	{

		char *p1 , *p2;

		int len;

 

		p1 = strstr(url , "://")+3;

		p2 = strstr(p1 , "/");

		if(NULL == p2)

		{

			p2 = url + strlen(url);

		}

 

		len = p2 - url;

		p1 = malloc(len + strlen(newUri)+1);

		if(NULL == p1)

		{

			printf("malloc error\n");

			return NULL;

		}

 

		memcpy(p1 , url , len);

		strcpy(p1+len , newUri);

		return p1;

	}

	else

	{

		return strdup(newUri);

	}

}

 

 

 

int http_process(char *file_url)

{

	ghttp_request *req = NULL;

	ghttp_status status;

	int statusCode;

	int ret;

	int filesize;

	int redirect_cnt = 0;

	char *url = file_url;

	char *p;

 

	bzero(buffer , sizeof(buffer));

 

	/***初始化a-res庫****/

	//ares_library_init(ARES_LIB_INIT_ALL);

AGAIN:

	req = ghttp_request_new(http_interrupt , &mCancelHttp);

	if(NULL == 	req)

	{

		printf("request new err !!\n");

		goto EXIT;

	}

 

	/***設置請求的url**/

	if(ghttp_set_uri(req , url) != 0)

	{

		printf("set uri err !!\n");

		goto EXIT;

	}

 

	/***設置自定義http協議頭 ,非必須***/

//	ghttp_set_header(req , "User-Agent","VLC/2.2.4LibVLC/2.2.4\n");

 

	/**設置get方法下載數據**/

	ghttp_set_type(req , ghttp_type_get);

 

	ghttp_prepare(req);

 

	/***連接服務器***/

	status = ghttp_connect(req , 011 , 011);

//	status = ghttp_connect(req , 0 , 4095);

	if((status != ghttp_done)&&(status != ghttp_error_no_support_range))

	{

		printf("http fail ...\n");

		goto EXIT;

	}

 

 

	/****獲取http 服務器的響應碼***/

	statusCode = ghttp_status_code(req);

 

	/***處理重定向****/

	if(statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307)

	{

		if(redirect_cnt >= 3)

		{

			printf("redirect too much times \n");

			goto EXIT;

		}

 

		char *p = _get_redirect_url(url , req);

		if(NULL == p)

		{

			goto EXIT;

		}

		

		if(redirect_cnt > 0)

		{

			free(url);

		}

		

		url = p;

 

		redirect_cnt++;

		ghttp_request_destroy(req);

		goto AGAIN;

 

	}

 

 

	/***開始獲取數據***/

	filesize = ghttp_get_size(req);

	ret = ghttp_read(req , buffer , 4095);

	if(ret < 0)

	{

		printf("http get data fail , ret = %d\n",ret);

	}

	else if(ret == 0)

	{

		printf("http get data success filesize :%d\n",filesize);

	}

	else

	{

		printf("http get data ret : %d\n",ret);

	}

 

 

	/****釋放http請求資源****/

	ghttp_request_destroy(req);

	if((redirect_cnt > 0)&& (NULL != url))

	{

		free(url);

	}

	printf("the data:[%s]\n",buffer);

 

	/***json 解析****/

	printf("-------------------++++josn++++-------------------\n");

	dedata(buffer);

	return 0;

 

 

EXIT:

 

	if(NULL != req)

	{

		ghttp_request_destroy(req);

	}

 

	if((redirect_cnt > 0)&& (NULL != url))

	{

		free(url);

	}

 

 

	return -1;

}	

 

 

/****main*****/

int main(int argc , char *argv[])

{

	int ret = -1;

	char *url="http://xzxtest.com/test/abc/listSubAlbum?sn=10086&flag=0";

	ret = http_process(url);

	return 0;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章