cJson源代码解读

一、cJson介绍

首先对于json最好的解释(含图解):https://www.json.org/json-en.html

cJson的源代码链接(github):https://github.com/DaveGamble/cJSON

别看项目文件那么多,其实核心代码都在下图两个文件中
在这里插入图片描述

cJson项目介绍(大致从README.md翻译而来):

cJSON旨在成为您可以完成工作的最愚蠢的解析器。它是C的单个文件,也是单个头文件。
总体代码量才1000行左右,相对来说还是非常容易去理解。

二、使用方式

使用教程:https://blog.csdn.net/weixin_42887343/article/details/114318670

三、源码分析

1、宏定义
首先使用宏定义了json文中对象的数据类型,如下所示

/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Int 3
#define cJSON_Double 4
#define cJSON_String 5
#define cJSON_Array 6
#define cJSON_Object 7
#define cJSON_IsReference 256

定义的上述宏用于cJSON结构体类型的分类。所以后文中,不管说的对象、数组、还是节点,其实都是cJSON结构体的实例化,只是不同定义的类型和用处不一样,称呼所以也不一样而已。
在这里插入图片描述
json文件结构内容如上图所示,框1是一个cJSON_Object类型,框2是cJSON_String类型,框3是cJSON_Array类型。
在程序中对该json文件结构的描述,就是使用n个实例化的cJSON结构体表示,每个节点就是一个实例化的cJSON结构体。

2、结构体
cJson中 最重要 的结构体如下所示,cJSON中json数据采用双向链表来存储。

/* The cJSON structure: */
typedef struct cJSON
{
    struct cJSON *next, *prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

    int type; /* The type of the item, as above. */

    char *valuestring; /* The item's string, if type==cJSON_String */
    uint64 valueint; /* The item's number, if type==cJSON_Number */
    double valuedouble; /* The item's number, if type==cJSON_Number */
    int sign;   /* sign of valueint, 1(unsigned), -1(signed) */

    char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;

(1)cJSON *next, *prev; 定义的双向链表指针。
(2)cJSON *child 定义的子对象指针。
(3)int type; 定义的该对象的类型,具体类型上面宏定义已经说明。
(4)对象数据存储,由于对象数据类型不确定,所以包含多个数据类型,如下:

    char *valuestring; /* The item's string, if type==cJSON_String */
    uint64 valueint; /* The item's number, if type==cJSON_Number */
    double valuedouble; /* The item's number, if type==cJSON_Number */
    int sign;   /* sign of valueint, 1(unsigned), -1(signed) */

注释说明了,不同类型时候,不同的变量有效。
(5)char *string 该对象的对象名,和4组合在一起构成 “键值对” 。

3、函数
cJSON操作JSON对象实质就是操作链表的过程。本次分析cJSON添加对象和删除对象的操作。

  • json文件解析:------------------------------------------------------------------------------------------------------
    json文件解析成cJSON结构体实体,将整个json文件内容转为代码中的实例化的结构体内容。
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
  • json文件输出:------------------------------------------------------------------------------------------------------
    和json文件解析相反,下面函数是将代码中的实例化的结构体内容,转为json文件保存。
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
  • 删除所有实例化的cJson结构体对象:---------------------------------------------------------------------
    在前面的cJSON_Parse函数中,创建cJSON结构体对象时申请了内存,所以必定由内存释放的函数。从下面代码看出,只要传入根对象(root),其之下的所有子对象都将被删除。
/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
    cJSON *next;
    while (c)
    {
        next = c->next;
        if (!(c->type & cJSON_IsReference) && c->child)
            cJSON_Delete(c->child);
        if (!(c->type & cJSON_IsReference) && c->valuestring)
            cJSON_free(c->valuestring);
        if (c->string)
            cJSON_free(c->string);
        cJSON_free(c);
        c = next;
    }
}
  • 创建对象操作:------------------------------------------------------------------------------------------------------
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull();
extern cJSON *cJSON_CreateTrue();
extern cJSON *cJSON_CreateFalse();
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateDouble(double num, int sign);
extern cJSON *cJSON_CreateInt(uint64 num, int sign);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray();
extern cJSON *cJSON_CreateObject();

其实上述函数的实现基本差不多,只是cJSON结构体的type成员赋值不一样,用于对象的区分,如下源代码实现就可看出,只有 item->type赋值存在区别。

cJSON *cJSON_CreateArray()
{
    cJSON *item = cJSON_New_Item();
    if (item)
        item->type = cJSON_Array;
    return item;
}
cJSON *cJSON_CreateObject()
{
    cJSON *item = cJSON_New_Item();
    if (item)
        item->type = cJSON_Object;
    return item;
}
  • 创建数组操作:------------------------------------------------------------------------------------------------------
/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(int *numbers, int sign, int count);
extern cJSON *cJSON_CreateFloatArray(float *numbers, int count);
extern cJSON *cJSON_CreateDoubleArray(double *numbers, int count);
extern cJSON *cJSON_CreateStringArray(const char **strings, int count);

看源代码,函数返回的都是第一个对象的地址,即数组首地址。

  • 对象删除操作:------------------------------------------------------------------------------------------------------
/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
  • 对象修改操作:------------------------------------------------------------------------------------------------------
/* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string,
                cJSON *newitem);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值