json-c-0.9库解析

来源:互联网 发布:淘宝店铺托管协议 编辑:程序博客网 时间:2024/06/04 18:04

json-c-0.9库解析


  • 预备知识
    • linux内核哈希表hlist

项目中使用json格式字符串进行进程间通信,使用json-c-0.9库进行字符串解析和设置,现将json-c-0.9库进行说明,欢迎指正~~


1. 编译

  1. ./configure CC= –host= –prefix=PATH
    指定编译器、主机类型、安装路径(绝对路径),默认路径/usr/local
  2. make && make install
    修改config.h.in屏蔽#undef malloc 和 #undef realloc后执行,
    这样json就已经安装成功。
  3. -std=c99 -I/PATH/incldue/json -L/PATH/lib -ljson
    在程序中使用json的api只需要在编译程序时添加以上信息
    例如这样编译库中test1.c:
    gcc test1.c -o test1 -std=c99 -I/PATH/incldue/json -L/PATH/lib -ljson

2. 数据结构(data structures)

比较重要的数据结构:

1. struct json_object
struct json_object{  enum json_type o_type;            //json对象类型  json_object_delete_fn *_delete;   //free json对象  json_object_to_json_string_fn *_to_json_string;   //转换json对象为json格式的字符串  int _ref_count;                   //json对象引用计数,初始化为1  struct printbuf *_pb;             //存储json对象转换后的字符串内存区域地址  union data {    boolean c_boolean;              //boolean类型json对象的数值    double c_double;                //double类型json对象的数值    int c_int;                      //int类型json对象的数值    struct lh_table *c_object;      //存储object类型json对象的hash_table地址    struct array_list *c_array;     //存储array类型json对象的字符串数组地址    char *c_string;                 //存储string类型json对象的地址  } o;};
2.  struct json_tokener
struct json_tokener{  char *str;  struct printbuf *pb;      //用于分类存储待解析字符串的buffer  int depth;                //结构体成员stack的depth  int is_double;            //value是double or int  int st_pos;               //string中某字符的position,string包括:null,true,false,unicode  int char_offset;          //某字符在待解析字符串中的offset  ptrdiff_t err;            //字符串解析出错代码  unsigned int ucs_char;    //unicode的值  char quote_char;          //存储引号"  struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH]; //存储待解析字符串中所有的json对象};
3. struct json_object 和 struct json_tokener 的成员struct printbuf定义如下,定义一个buffer,用于存储字符串;
struct printbuf {  char *buf;  int bpos;     //buf中已经使用的数量  int size;     //buf的size};
4. struct json_tokener 的成员struct json_tokener_srec定义如下,定义一个stack,用于存储不同类型object对象;
struct json_tokener_srec{  enum json_tokener_state state, saved_state;  struct json_object *obj;  //暂未使用  struct json_object *current;  char *obj_field_name;     //object某一个field的name};

3. 文件(files)

获取json-c-0.9.tar.gz解压后,包含的源码文件如图,下面内容大致介绍文件的主要代码:

json-c-0.9源码文件列表

  • json_object.c
    定义json对象的操作函数,包括新建、删除、转换、添加等函数;

    1. json_object_new()/json_object_to_json_string()/json_object_generic_delete()  三个函数分别new一个json对象/转换json对象为json格式的字符串/删除json对象,相当于父类。

json_object_new()实现:

    static struct json_object* json_object_new(enum json_type o_type)    {        struct json_object *jso;        jso = (struct json_object*)calloc(sizeof(struct json_object), 1);       //new一个json_object对象,并赋值        if(!jso) return NULL;        jso->o_type = o_type;        jso->_ref_count = 1;        jso->_delete = &json_object_generic_delete;        ...        return jso;    }

json_object_to_json_string()实现

    const char* json_object_to_json_string(struct json_object *jso)    {        if(!jso) return "null";        if(!jso->_pb) {        if(!(jso->_pb = printbuf_new())) return NULL;        } else {            printbuf_reset(jso->_pb);//如果存在,则复位存储json对象转换后的字符串的内存区域,否则new一个新区域        }            if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL;    //依据传入的json对象(struct json_object *jso),                                    //jso->_to_json_string(jso, jso->_pb)调用相应的json_object_**_to_json_string()函数            return jso->_pb->buf;    }

json_object_generic_delete()实现

    static void json_object_generic_delete(struct json_object* jso)    {        ...        printbuf_free(jso->_pb);        free(jso);    }
    2.  json_object_new_**()/json_object_**_to_json_string()/json_object_**_delete()       三个系列函数分别new一个“子类”的json对象/转换“子类”的json对象为json格式的字符串/删除“子类”的json对象;       其中的“子类”的json对象包括boolean、double、int、object、array、string等类型;

以object类型json对象为例:

json_object_new_**()实现

    struct json_object* json_object_new_object(void)    {        struct json_object *jso = json_object_new(json_type_object);        if(!jso) return NULL;        jso->_delete = &json_object_object_delete;                  //在json_object_new()基础上填充._to_json_string、.o.c_object方法,        jso->_to_json_string = &json_object_object_to_json_string;  //并覆写._delete方法        jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,                        NULL, &json_object_lh_entry_free);        return jso;    }

json_object_**_to_json_string()实现

    static int json_object_object_to_json_string(struct json_object* jso,                     struct printbuf *pb)    {        int i=0;        struct json_object_iter iter;        sprintbuf(pb, "{"); //object类型json对象的json格式字符串开始        /* CAW: scope operator to make ANSI correctness */        /* CAW: switched to json_object_object_foreachC which uses an iterator struct */        json_object_object_foreachC(jso, iter) {                //遍历json对象所有的key和value            if(i) sprintbuf(pb, ",");            sprintbuf(pb, " \"");            json_escape_str(pb, iter.key);            sprintbuf(pb, "\": ");            if(iter.val == NULL) sprintbuf(pb, "null");            else iter.val->_to_json_string(iter.val, pb);   //依据json对象(iter.val),选择相应的json_object_**_to_json_string()            i++;        }        return sprintbuf(pb, " }"); //object类型json对象的json格式字符串结束    }

json_object_**_delete()实现

    static void json_object_object_delete(struct json_object* jso)    {            lh_table_free(jso->o.c_object); //free hash_table        json_object_generic_delete(jso);    //free json对象    }
    3. json_object_get()/json_object_put()      增加json对象引用计数/减少json对象引用计数
    4. json_object_object_add()/json_object_object_get()/json_object_object_del()        添加一个feild到object类型的json对象/从object类型的json对象获取一个feild/删除object类型的json对象中一个feild
    5. json_object_array_add()/json_object_array_put_idx()/json_object_array_get_idx()        添加一个element(json对象)到array类型的json对象尾部/添加一个element到array类型的json对象的        某个位置/获取array类型的json对象的某个位置的element

  • json_tokener.c
    定义解析字符串为json对象函数以及两个重要的宏POP_CHAR(dest, tok)和ADVANCE_CHAR(str, tok)

POP_CHAR(dest, tok)

#define POP_CHAR(dest, tok)                                                  \(((tok)->char_offset == len) ?                                          \     (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \        (((tok)->err = json_tokener_success), 0)                              \        :                                                                   \        (((tok)->err = json_tokener_continue), 0)                             \    ) :                                                                 \     (((dest) = *str), 1)                                                 \ )      //将字符*str赋值给dest,并返回1;当到达字符串结尾(tok->char_offset == len)时检查depth、state和saved_state,设置tok->err,并返回0

ADVANCE_CHAR(str, tok)

#define ADVANCE_CHAR(str, tok) \    ( ++(str), ((tok)->char_offset)++, c)   //遍历字符串str,同步递增tok->char_offset,并返回字符c        //和POP_CHAR(c, tok)一起使用,实现对字符串str的字符进行遍历,并设置遍历的结果状态(tok->err)
定义的函数包括新建/删除json_tokener对象函数json_tokener_new()/json_tokener_free(),以及解析函数json_tokener_parse**();其中json_tokener_parse_ex()函数很重要,此函数通过state和saved_state两个状态控制函数流程,state和saved_state 取下面枚举值;
enum json_tokener_state {    json_tokener_state_eatws,                   //ew    json_tokener_state_start,                   //st    json_tokener_state_finish,                  //fi    ...    json_tokener_state_string,                 //str    json_tokener_state_string_escape,          //str_esc    json_tokener_state_escape_unicode,         //uni    ...    json_tokener_state_array,                  //arr    json_tokener_state_array_add,              //arr_a    json_tokener_state_array_sep,              //arr_s    json_tokener_state_object_field_start,     //ofs    json_tokener_state_object_field,           //of    json_tokener_state_object_field_end,       //ofe    json_tokener_state_object_value,           //ov    json_tokener_state_object_value_add,       //ova    json_tokener_state_object_sep              //os};
json_tokener_parse_ex() 函数可以解析boolean、double、int、object、array、string等类型的json对象,以object类型的json对象的解析过程为例,说明解析流程(重点介绍解析过程中state和saved_state 转换过程,详细流程查看源码)

object类型json对象解析状态变换流程

  • linkhash.c
    这个文件中函数用于处理存储object类型json对象的hash_table,包括新建hash_table函数lh_table_new()/lh_**_table_new(),删除hash_table
    函数lh_table_free(),添加record到hash_table函数lh_table_insert(),删除record函数lh_table_delete()/lh_table_delete_entry(),查找record
    函数lh_table_lookup()/lh_table_lookup_entry();
    关于hash_table的知识请参考预备知识 : linux内核哈希表hlist;

  • arraylist.c
    这个文件中函数用于处理存储array类型json对象的arraylist,包括新建arraylist函数array_list_new(),删除arraylist函数array_list_free(),
    添加元素到arraylist函数array_list_add()/array_list_put_idx(),查找元素函数array_list_get_idx();

  • debug.c
    定义不等等级的日志输出函数以及对应的宏,MC_DEBUG()/mc_debug()/..;

  • printbuf.c
    定义内存操作函数,新建函数printbuf_new(),内存拷贝函数printbuf_memappend()等;

  • json_util.c
    定义从文件读取字符串解析为json对象函数json_object_from_file()和将json对象转化为json格式字符串写入文件函数json_object_to_file();


4. json格式通信的收发流程

  • 接收:
    read()(读取字符串数据)
    –> json_tokener_parse()(从字符串数据中解析json对象)
    –> json_object_get_*()(从json对象中获取数据value,如int、double、string、array、object等)
  • 发送:
    json_object_new_*()(生成json对象)
    –> json_object_object_add()/json_object_array_add()/json_object_to_json_string().. (往json对象添加数据并转换字符串数据)
    –> write()(发送字符串数据)

5. 举例

项目中使用json格式字符串进行进程间通信,流程如下:
读取进程间通信数据(字符串) –> 解析出json对象 –> 处理json对象 –> … –> 生成json对象并添加数据 –> 转换json对象为json格式字符串并发送


6. 小结

本文简绍项目中使用的json-c-0.9库解析、处理json格式字符串的实现流程,并简单说明使用json-c-0.9进行通信的原理,欢迎指正和讨论^_^。


疑问

  1. json_object.h 30~38行的定义有什么用?
    printbuf、lh_table、… 这些结构体在别的地方已经定义,再次定义的作用是什么..
    /* forward structure definitions */    typedef int boolean;    typedef struct printbuf printbuf;    typedef struct lh_table lh_table;    typedef struct array_list array_list;    typedef struct json_object json_object;    typedef struct json_object_iter json_object_iter;    typedef struct json_tokener json_tokener;

2 0
原创粉丝点击