使用cJSON的注意了 + 具体使用

本文要点:

处理10k的json数据大概会额外用掉50k左右的ram,谨记,没那么大空间预留就别玩了

cJSON库下载

cJSON-master.zip-其它文档类资源-CSDN下载 (应该是被我设置0积分下载的)

https://github.com/DaveGamble/cJSON  (github下载)

cJSON解析:

使用cJSON之前先了解下其数据结构(在cJSON.h文件)

/* 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 */
    int valueint;                /* The item's number, if type==cJSON_Number */
    double valuedouble;            /* The item's number, if type==cJSON_Number */

    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;

 其中valuestring,valueint,valuedouble就是你所需要字段的值,具体用法看下面吧。

下面给出一个实例:

{
	"code": 0,
	"data": {
		"list1": {
			"define1": "this is define 1",
			"define2": "this is define 2"
		},
		"list2": [
			{
				"intNum": 33,
				"doubleNum": 12.1
			}
		]
	},
	"detailMsg": "",
	"errorCode": 0,
	"extMap": {},
	"fail": true,
	"msg": "",
	"success": true
}

我们可以看到这块数据有3层,第一步先解析整个json

假如整个json用buffer变量装着

cJSON *root=NULL,*L2Object = NULL,*L3Object = NULL ;//root表示最开始层,L2表示第二层,L3表示第三层
char* buffer;//这里当buffer里面已经有数据了

if(!(root = cJSON_Parse((char*)buffer))) 
{
    return ;    //这里表示root返回值是空,表示解析json失败
}

1.获取code的值,从上面可以看到code的值是一个整数(其他同理):

code = cJSON_GetObjectItem(root,"code")->valueint;

2.获取data里面字段的值,先需要获取到data相对应的控制指针

L2Object = cJSON_GetObjectItem(root,"data");

这样就得到data的控制指针,然后同理可进入第三层

那么获取define1,2的值:

L3Object = cJSON_GetObjectItem(L2Object ,"list1");先获取到list1指针

define1 =  cJSON_GetObjectItem(L3Object ,"define1")->valuestring;

define2 =  cJSON_GetObjectItem(L3Object ,"define2")->valuestring;

那么获取intNum,doubleNum的值:

L3Object = cJSON_GetObjectItem(L2Object ,"list2");先获取到list2指针

intNum=  cJSON_GetObjectItem(L3Object ,"intNum")->valuent;

doubleNum=  cJSON_GetObjectItem(L3Object ,"doubleNum")->valuedouble;

3.获取true,false的值

介绍下type的值(在cJSON.h文件)

/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6

if(cJSON_GetObjectItem(root,"fail")->type == cJSON_True)

{printf("fail is ture");}

至此这种类型就是这样获得

还有解析数组类的

[
	{
		"new1": "",
		"new2": ""
	},
    {
		"new1": "",
		"new2": ""
	}
]

同样(下面默认都是正常获取到,不考虑异常),

root = cJSON_Parse((char*)buffer);

if( NULL != root )

{

        cJSON *L2Object = root ->child;

        while( L2Object != NULL )

        {

                char * new1   = cJSON_GetObjectItem( client_list , "new1")->valuestring ;

                char * new2= cJSON_GetObjectItem( client_list , "new2")->valuestring ;

                printf("new1: %s  new2: %s\r\n",new1,new2);

                L2Object = L2Object ->next ;

         }

}

{
    "list": [
        "0.0.0.0",
        "1.1.1.1",
        "2.2.2.2"
    ]
}

root = cJSON_Parse((char*)buffer);

L2Object = cJSON_GetObjectItem(root,"list");

int  array_size   = cJSON_GetArraySize ( L2Object );//获取list有多少个数据

for( iCnt = 0 ; iCnt < array_size ; iCnt ++ )

{

        cJSON * pSub = cJSON_GetArrayItem(L2Object , iCnt);

        if(NULL == pSub ){ continue ; }

        char * ivalue = pSub->valuestring ;

        printf("list[%d] : %s\r\n",iCnt,ivalue);

    }

cJSON生成:

首先,来个最普通常见的

{
        "define1":      "this is define1",
        "define2":      "this is define2",
        "numInt":       12,
        "numDouble":    12.12,
        "sta":  true
}

cJSON*root = cJSON_CreateObject();//创建一个目录并申请内存 
cJSON*item = NULL;//用于创建一个字段
char *out;
double num = 12;

/*写法1*/

item = cJSON_CreateString("this is define1");
cJSON_AddItemToObject(root, "define1", item);//这里item申请的内存会转到root上,不需要手动释放,其他同理
item = cJSON_CreateString("this is define2");
cJSON_AddItemToObject(root, "define2", item);
item = cJSON_CreateNumber(num);
cJSON_AddItemToObject(root, "numInt", item);
item = cJSON_CreateNumber(12.12);
cJSON_AddItemToObject(root, "numDouble", item);
item = cJSON_CreateTrue();
cJSON_AddItemToObject(root, "sta", item);
out = cJSON_Print(root);        //注意,这里不是打印输出,是将json格式化输出到一块内存上,并返回指针
printf("%s\n", out);        //这里才是打印显示
cJSON_Delete(root);
free(out);                        //这两处必须释放内存,否则会造成内存泄漏。

/*写法2,直接省略使用item的步骤,下面的方法默认用这个来做*/

cJSON_AddItemToObject(root, "define1", cJSON_CreateString("this is define1"));
cJSON_AddItemToObject(root, "define2", cJSON_CreateString("this is define2"));
cJSON_AddItemToObject(root, "numInt", cJSON_CreateNumber(num));
cJSON_AddItemToObject(root, "numDouble", cJSON_CreateNumber(12.12));
cJSON_AddItemToObject(root, "sta", cJSON_CreateTrue());
out = cJSON_Print(root);
printf("%s\n", out);
cJSON_Delete(root);
free(out);

PS:

对于out = cJSON_Print(root);这条,其实常用的是另外一个输出函数 char *cJSON_PrintUnformatted(cJSON *item)  这个,两者的区别是上面那个是格式化输出,就是人看起来比较直观,但是只是给人看的,不是给程序看的(看上面的例子)。下面这个生成就是正常地生成,一行过。具体可自行输出看看。

然后,下一个

{
        "object1":      {
                "firstName":    "Tony",
                "lastName":     "Jeny"
        },
        "object2":      {
                "movie":        "Now You See Me"
        }
}

其实可以吧json看成一个文件系统,root就是根目录,object1,object2就是根目录下的子目录,firstName就是文件。再想往下建目录就同理操作即可

cJSON *root = cJSON_CreateObject();        //相当于根目录
cJSON *obj_floor1;        //相当于子目录

obj_floor1 = cJSON_CreateObject();
cJSON_AddItemToObject(obj_floor1, "firstName", cJSON_CreateString("Tony"));
cJSON_AddItemToObject(obj_floor1, "lastName", cJSON_CreateString("Jeny"));
cJSON_AddItemToObject(root, "object1", obj_floor1);        //将obj_floor1放到root下并命名为object1

obj_floor1 = cJSON_CreateObject();
cJSON_AddItemToObject(obj_floor1, "movie", cJSON_CreateString("Now You See Me"));
cJSON_AddItemToObject(root, "object2", obj_floor1);
out = cJSON_Print(root);
printf("%s\n", out);
cJSON_Delete(root);
free(out);

再下一个(数组型)

[{
                "lastName":     "我是谁",
                "age":  123
        }, {
                "lastName":     "你是谁",
                "sta":  true,
                "age":  321
        }]

cJSON*array = cJSON_CreateArray();
cJSON*obj_person
char *out;

obj_person = cJSON_CreateObject();
cJSON_AddItemToObject(obj_person, "lastName", cJSON_CreateString("我是谁"));
cJSON_AddItemToObject(obj_person, "age", cJSON_CreateNumber(123));
cJSON_AddItemToArray(array, obj_person);

obj_person = cJSON_CreateObject();
cJSON_AddItemToObject(obj_person, "lastName", cJSON_CreateString("你是谁"));
cJSON_AddItemToObject(obj_person, "sta", cJSON_CreateTrue());
cJSON_AddItemToObject(obj_person, "age", cJSON_CreateNumber(321));
cJSON_AddItemToArray(array, obj_person);

out = cJSON_Print(array);
printf("%s\n", out);
cJSON_Delete(array);
free(out);

补充(后续可能会有更新)

1.如果使用cJSON_CreateNumber()后,发现输出的数小数点后的位数特别多(有可能是旧版本有这个问题吧,具体自行测测)

如 cJSON_AddItemToObject(root, "numDouble", cJSON_CreateNumber(12.12));

得到结果是  "numDouble":  12.12000000  无法限制小数位后面的位数

更改如下(修改cJSON.c文件)

static char *print_number(cJSON *item,printbuffer *p)
{
	char *str=0;
	double d=item->valuedouble;
	if (d==0)
	{
		if (p)	str=ensure(p,2);
		else	str=(char*)cJSON_malloc(2);	/* special case for 0. */
		if (str) strcpy(str,"0");
	}
	else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
	{
		if (p)	str=ensure(p,21);
		else	str=(char*)cJSON_malloc(21);	/* 2^64+1 can be represented in 21 chars. */
		if (str)	sprintf(str,"%d",item->valueint);
	}
	else
	{
		if (p)	str=ensure(p,64);
		else	str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
		if (str)
		{
			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)			sprintf(str,"%e",d);
			else												sprintf(str,"%f",d);
		}
	}
	return str;
}

最后一个sprintf(str,"%f",d);改成sprintf(str,"%.2lf",d);

这样可以限制输出小数点后两位

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
引用和提供了关于在Windows上使用cJSON的编译和安装步骤。首先,你需要下载lua-cjson的源码,并解压它。接下来,你需要修改makefile文件,取消注释掉有关Windows的相关内容,并设置一些参数。然后,你需要手动编译源码并生成cjson.dll库文件。你可以在引用中找到具体的编译命令。最后,你需要将编译好的cjson.dll文件复制到Lua的clibs目录下。 以下是在Windows上使用cJSON的步骤: 1. 下载lua-cjson的源码并解压。 2. 打开makefile文件,并取消注释掉Windows相关的内容。 3. 根据需要修改makefile文件中的参数。 4. 在命令终端中进入源码路径。 5. 执行mingw32-make命令来编译源码。 6. 使用dir命令来查看生成的dll文件。 7. 将源码路径下的cjson.dll文件复制到Lua的clibs目录下。 请注意,这些步骤是基于引用、和提供的信息,用于在Windows上编译和使用cJSON库。具体的操作和文件路径可能因个人环境而有所不同。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [windows下lua三方库lua-cjson的编译](https://blog.csdn.net/qq_35566365/article/details/88625009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Lua cjson库在windows版本cjson.dll](https://download.csdn.net/download/asmcvc/8668175)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值