初识cJSON

先把 cJSON的结构体定义po上来:
cJSON结构体
先讲怎么用,再讲每一步操作的作用,最后有可能的话再讲原理。

直接先po个简单示例,看看我们如何通过cJSON来解析一个JSON数据。
cJSON解析实例
先试着能不能看懂(估计是看不懂了),算了算了,直接看看不懂,先来讲点“前言”。
.
.
.
.
我们先来讲讲几个用到的函数。
首先是 **cJSON cJSON_Parse(const char value);
可以看见,函数的返回类型是一个cJSON指针。函数的传入参数是一个字符指针。该函数的作用是将json格式的字符串转换成json对象。具体为:将一个JSON数据包(即传入的字符指针所指向地址存放的数据),按照cJSON结构体的结构把整个数据包序列化,并在堆中开辟一块内存来存储cJSON结构体(这个作用解释得跟没解释差不多hhh,先简单理解成初始化一段JSON数据包),而如果传入该函数的(也就是该char指针所指向的字符串)不是一段JSON格式的数据,则函数返回NULL指针。如果传入的是JSON数据包,且“初始化”成功,则函数返回一个指向内存块中的cJSON的指针(也就是返回一个cJSON指针,该指针指向该JSON数据包)。
举个例子:

char example[] ={
    
    \“name\”:\”How\”,\”age\”:18};	//一个存储json数据包的字符串
cJSON * json;	//创建一个名为json的cJSON指针
json = cJSON_Parse(example);	//判断example是否为JSON数据包
//如果是,则序列化example,然后返回一个cJSON指针
//将返回的指针赋给json变量,即,json指针变量现在指向example这个JSON数据包

.

再来看看 **cJSON *cJSON_GetObjectItem(cJSON object,const char string);
同样的,函数的返回类型是一个cJSON指针。函数的传入参数是一个cJSON指针,和一个字符指针。该函数的作用是,获取JSON数据包中某字符串所对应的字段值,并返回一个指向JSON的cJSON指针。这么说可能不好理解,我们还是来举个例子:

char example[] ={
    
    \“name\”:\”How\”,\”age\”:18};
cJSON * json;
cJSON * json_age;//这里我们新建一个名为json_age的cJSON指针
json = cJSON_Parse(example);
json_age = cJSON_GetObjectItem(json, "age");//这句代码的作用是:
//向函数提供一个指向JSON数据包的cJSON指针,即json
//以及提供一个该JSON数据包中的某个key的变量名
//那么函数就会返回一个指向该key变量的值value的cJSON指针
//将返回的指针赋给json_age,于是json_age现在指向age的值
//这样的话,我们就可以通过json_age来访问并打印该值了,如:
if( json_age -> type == cJSON_Number )	//判断age的值是否为数字
{
    
    
	printf("age: %d\n", json_age->valueint);	//若是,以访问成员变量的方式打印
}

(这个时候再回头看看cJSON结构体的定义,里面就有type和valueint,即是cJSON的属性之一)
.
.
再来看看 **char cJSON_Print(cJSON item);
返回类型是一个字符指针。传入参数是一个cJSON指针。该函数的作用是,从传入指针所指的cJSON数据中提取JSON对象的数据,并在堆中开辟一块char*的内存空间存储JSON字符串。即从cJSON对象中获取有格式的JSON对象。(cJSON结构体中不但包含JSON结构的数据——key和value,还包含了其它一些属性作为成员变量——如type,valueint)所以通过cJSON_Print函数就能把cJSON中的JSON数据提取出来,并返回给一个字符指针。
还是来举个例子:

char example[] ={
    
    \“name\”:\”How\”,\”age\”:18};
cJSON * json;
char * output;
json = cJSON_Parse(example);
output = cJSON_Print(json);
printf("%s\r\n",output);

这样就把example解析成JSON字符串并输出了。但是有人就会问了,这不是瞎折腾吗?example不是本来就是JSON数据格式的吗?(%@¥&@%63¥emmm我也不知道…)
.
.
再来看看 *void cJSON_Delete(cJSON c);
这个很好理解,其作用就是释放cJSON指针占用的内存。
举例比如cJSON_Delete(json); cJSON_Delete(json_age);
.
.
.
.
好了,有了以上的了解,我们再回过头来看文章一开头的代码:

#include <stdio.h>
#include <stdlib.h>
#include "cjson/cJSON.h"

//新建一个名为text的json格式的字符串
char text[] = "{\"timestamp\":\"2019-03-03 08:45:57\", \"value\":1}";

void main(int argc, const char *argv[])
{
    
    
    cJSON *json, *json_value, *json_timestamp;	//三个cJSON指针变量
    json = cJSON_Parse(text);	//将text字符串转换成cJSON对象
    if(NULL == json)	//如果text不是json格式
    {
    
    
        printf("Error before: [%s]\n", cJSON_GetErrorPtr());
        return -1;
	}
	
	//用json_value指针指向json变量所指的cJSON对象中value的值
    json_value = cJSON_GetObjectItem(json, "value");
    if(json_value->type == cJSON_Number)		//如果该值符合我们所想
    {
    
    
        printf("value: %d\n", json_value->valueint);
	}
	
	//同理
    json_timestamp = cJSON_GetObjectItem(json, "timestamp");
    if(json_timestamp->type == cJSON_String)
    {
    
    
        printf("%s\n", json_timestamp->valuestring);
	}
	
	//释放json这个cJSON变量所占用的内存
    cJSON_Delete(json);
}

以上,我们就实现了JSON字符串的解析,其目的就是使之成为一个对象,让我们能够去访问该字符串里面的各种数据。

那么,前面我们是通过已有JSON字符串来解析成对象,那么我们能不能反过来,自己创建一个JSON对象呢?答案当然是可以的。能力有限,不解释,直接po代码了:

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

void main(void)
{
    
    
	cJSON * student_json;	//学生信息
	cJSON * grades_json;	//成绩信息
	char * output = NULL;	//用于输出json字符串
	
	/
	student_json = cJSON_CreateObject();
	grades_json = cJSON_CreateObject();
	
	cJSON_AddItemToObject(student_json, "name", cJSON_CreateString("陈how"));
	cJSON_AddItemToObject(student_json, "qq", cJSON_CreateNumber(772541523));
	cJSON_AddItemToObject(student_json, "sex", cJSON_CreateString("男"));
	cJSON_AddItemToObject(student_json, "status", cJSON_CreateString("damn-single"));
	cJSON_AddItemToObject(student_json, "成绩", grades_json);
	cJSON_AddItemToObject(grades_json, "专业课", cJSON_CreateString("awful"));
	cJSON_AddItemToObject(grades_json, "学科竞赛", cJSON_CreateString("not bad"));
	cJSON_AddItemToObject(grades_json, "文化素养", cJSON_CreateString("so-so"));
	cJSON_AddItemToObject(student_json, "备注", cJSON_CreateString("这是一条备注"));
	
	output = cJSON_Print(student_json);
	
	if( output == NULL )	printf("error!\r\n");
	else	printf("Info:\r\n %s \r\n", output);
	/
	cJSON_Delete(student_json);
	cJSON_Delete(grades_json);
	free(output);
	/

}

其输出结果为:
输出结果

P.S. 上面这段代码一开始我在STM32里面敲,然后用串口调试助手打印信息,结果不行,cJSON_Print(student_json)返回的是NULL,原因大概是因为由于是在STM32里面,然后类似于内存分配啥的问题,内存不够之类(因为代码我单条单条在STM32都能实现,但是一次性要打印这么多数据就崩了)

以上。

扫描二维码关注公众号,回复: 12463520 查看本文章

参考资料:
全面详解c语言使用cJSON解析JSON字符
JSON的简单介绍&cJSON库使用(一)
cJSON详解
JSON介绍
cJSON的使用方法
STM32 keil环境下移植cJSON
STM32移植cJSON[注意用free()释放内存]
CSDN:去掉博客中的图片水印 /狗头

猜你喜欢

转载自blog.csdn.net/weixin_44692935/article/details/103001072