使用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;

}

 

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