[c]cJSON开源库介绍

cJSON,github仓库 cJSON repo

用C语言解析json转换为cJSON对象的开源库。

JSON全称: JavaScript Object Notation。

json:key-value类型。
json中有6种数据类型:数字(number,整数或浮点数)、字符串(string,在双引号中)、逻辑值(bool,true 或 false)、数组 (array,在方括号中)、对象 (object,在花括号中)、null。

cJSON

为什么使用cJSON

  • 代码轻量级
  • 使用广泛
  • 可移植性高

2016-9-9用benchmark测试各个json解析库的性能

Conformance

详细对比文档:https://github.com/miloyip/nativejson-benchmark

cJSON解析
在进行json解析的时候,通过type判断当前json的类型是哪一种,进行具体的解析。

/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False  (1 << 0)
#define cJSON_True   (1 << 1)
#define cJSON_NULL   (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array  (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw    (1 << 7) /* raw json */

cJSON核心数据结构

/* The cJSON structure: */
typedef struct cJSON
{
    struct cJSON *next;			//后置节点指针
    struct cJSON *prev;			//前置节点指针
    struct cJSON *child;		  //子节点指针
    
    int type;								//value 的类型
    char *valuestring;			//字符串数据
    int valueint;				       //整型数据
    double valuedouble;	   //浮点型数据
    
    char *string;				       //key 的名称
} cJSON;

具体的解析流程是把一个json字符串递归解析成cJSON对象的树结构。cJSON对象也可以转换成字符串。

字符串 --> cJSON树:cJSON_Parse函数,可以递归解析json,成为一个cJSON对象。
cJSON的Node中的type具体的值。具体来看一个例子:
请添加图片描述
左边是一个json,右边是cJSON解析时构建的结构。


cJSON中需要频繁的创建和释放内存,cJSON支持自定义内存函数。可以自定义malloc和free函数,数据结构如下,

typedef struct cJSON_Hooks
{
      void *(CJSON_CDECL *malloc_fn)(size_t sz);
      void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;

具体的使用方法是这样的,使用者实现一个my_mem_alloc和my_mem_free,通过cJSON_Hooks结构体传给cJSON,让cJSON创建新的item时使用使用者的内存管理函数。有一个全局的global_hooks,保存内存分配的函数。

void set_cJSON_mem_hooks(){
    cJSON_Hooks hooks = {
        .malloc_fn = my_mem_alloc,
        .free_fn   = (void(CJSON_CDECL*)(void* ptr))my_mem_free,
    };
    cJSON_InitHooks(&hooks);
}

CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) {
    if (hooks == NULL) {
        /* Reset hooks */
        global_hooks.allocate   = malloc;
        global_hooks.deallocate = free;
        global_hooks.reallocate = realloc;
        return;
    }

    global_hooks.allocate = malloc;
    if (hooks->malloc_fn != NULL) {
        global_hooks.allocate = hooks->malloc_fn;
    }

    global_hooks.deallocate = free;
    if (hooks->free_fn != NULL) {
        global_hooks.deallocate = hooks->free_fn;
    }
	...
}

创建一个节点时,例如调用cJSON_CreateNumber()函数,调用cJSON_New_Item创建cJSON节点,其中使用全局的global_hooks中的allocate进行内存分配。

CJSON_PUBLIC(cJSON*) cJSON_CreateNumber(double num) {
    cJSON* item = cJSON_New_Item(&global_hooks);
    if (item) {
        item->type        = cJSON_Number;
        item->valuedouble = num;

        /* use saturation in case of overflow */
        if (num >= INT_MAX) {
            item->valueint = INT_MAX;
        } else if (num <= (double)INT_MIN) {
            item->valueint = INT_MIN;
        } else {
            item->valueint = (int)num;
        }
    }

    return item;
}

static cJSON* cJSON_New_Item(const internal_hooks* const hooks) {
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
    if (node) {
        memset(node, '\0', sizeof(cJSON));
    }

    return node;
}

注意事项(小坑)

  • cJSON_Print()这个函数的返回值是一个字符串,可供打印。::std::cout << cJSON_Print(root) << ::std::endl;
  • cJSON_Print() 返回的字符串需要手动释放。cJSON_free();
  • cJSON_Parse()、cJSON_CreateXXX 返回的cJSON对象需要手动释放。cJSON_Delete();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值