使用json-c 体会

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 
#include 
#include 
#include 

typedef long long off64_t;

#include 
/**是否强制退出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;
}




你可能感兴趣的:(Linux,C语言,json-c,libghttp)