概述
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("{nt"data":ntt[n");
for(i = 0 ; i < total ; i++)
{
printf("ttt{"id":"%s","name":"%s","type":%d,"count":%dn",listdata[i].id , listdata[i].name,listdata[i].type,listdata[i].count);
}
printf("tt],nt"total":%d,nt"flag":%d,nt"result":%dn}",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 errorn");
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.4n");
/**设置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 = %dn",ret);
}
else if(ret == 0)
{
printf("http get data success filesize :%dn",filesize);
}
else
{
printf("http get data ret : %dn",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;
}
最后
以上就是腼腆人生为你收集整理的使用json-c 体会的全部内容,希望文章能够帮你解决使用json-c 体会所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复