cJSON解析JSON
一、为何选择cJSON
在处理JSON格式时,如果只是处理简单的协议,可以通过对字符串的操作来进行解析与创建,随着协议逐渐复杂化,经常会遇到一些未考虑周全的地方,需要进一步完善解析方法,此时使用一个比较完善的JSON解析库的需求就提出来了,基于方便引用的考虑,我们希望这个JSON解析库是用C语言实现的,同时为了避免太过复杂的C源码包含关系,最好是一个C文件来实现,通过在网络上的查找,发现cJSON是比较符合要求的,cJSON只有一个C文件和一个头文件,包含到项目源码中非常方便,而且其实现效率非常高。
二、cJSON的核心结构体
cJSON的核心结构体是一个名为cJSON
的结构体,理解了这个结构体,基本上对cJSON的使用就有了个基本概念了,该结构体具体定义如下:
typedef struct cJSON { struct cJSON* next, *prev; // 遍历数组或对象链的前向或后向链表指针 struct cJSON *child; // 数组或对象的孩子节点 int type; // key的类型 char *valuestring; // 字符串值 int valueint; // 整数值 double valuedouble; // 浮点数值 char *string; // key的名字 } cJSON;
1、数据存储方式:cJSON是使用链表来存储数据的,其访问方式很像一颗树,每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层,只有节点是对象或数组时才可以有孩子节点。
2、键的类型:type是键(key)的类型,一共有7种取值,分别是:False,True,NULL,Number,String,Array,Object,若是Number类型,则valueint或valuedouble中存储着值,若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值,若是String类型的,则valuestring中存储着值,可以访问valuestring得到值。
3、键的名称:string中存放的是这个节点的名字,可理解为key的名称。
三、解析JSON格式
1. 解析一个键值对
一个简单的键值对字符串,要解析的目标如下:
{"firstName":"Brett"}
要进行解析,也就是要分别获取到键与值的内容,我们很容易就能看出键为firstName,值为Brett,可是,使用cJSON怎么解析呢?对于这个简单的例子,只需要调用cJSON的三个接口函数就可以实现解析了,这三个函数的原型如下:
cJSON* cJSON_Parse(const char *value); cJSON* cJSON_GetObjectItem(cJSON *object, const char *string); void cJSON_Delete(cJSON *c);
解析过程描述如下:
1、首先调用cJSON_Parse()
函数,解析JSON数据包,并按照cJSON结构体的结构序列化整个数据包,使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放。
cJSON* root = cJSON_Parse(json_string);
2、调用cJSON_GetObjectItem()
函数,可从cJSON结构体中查找某个子节点名称(键名称),如果查找成功可把该子节点序列化到cJSON结构体中。
cJSON* item = cJSON_GetObjectItem(root, "firstName");
3、如果需要使用cJSON结构体中的内容,可通过cJSON结构体中的valueint
和valuestring
取出有价值的内容(即键的值),本例子中,我们直接访问item->valuestring
就获取到"Brett"的内容了。
4、通过cJSON_Delete()
,释放cJSON_Parse()
分配出来的内存空间。
cJSON_Delete(root);
这样就完成了一次cJSON接口调用,实现了解析工作,使用起来其实也很简单。
2. 解析一个结构体
我们来个复杂一点的,解析一个结构体,要解析的目标如下:
{ "person": { "firstName": "z", "lastName": "jadena", "email": "jadena@126.com", "age": 8, "height": 1.17 } }
看起来比一个键值对复杂多了,我们又需要学习新的接口函数了吗?答案是不需要!还是那三个函数就可以了,解析的步骤要复杂一些,下面按解析过程来描述一次:
1、根据JSON串中的对象,我们定义一个相应的结构体如下:
typedef struct { char firstName[32]; char lastName[32]; char email[64]; int age; float height; } PERSON;
2、还是调用cJSON_Parse()
函数,解析JSON数据包。
cJSON* root = cJSON_Parse(json_string);
3、调用一次cJSON_GetObjectItem()
函数,获取到对象person。
cJSON* object = cJSON_GetObjectItem(root, "person");
4、对我们刚取出来的对象person,多次调用cJSON_GetObjectItem()
函数,来获取对象的成员,此时要注意,不同的成员,访问的方法不一样:
cJSON* item; PERSON person; item = cJSON_GetObjectItem(object, "firstName"); memcpy(person.firstName, item->valuestring, strlen(item->valuestring)); item = cJSON_GetObjectItem(object, "lastName"); memcpy(person.lastName, item->valuestring, strlen(item->valuestring)); item = cJSON_GetObjectItem(object, "email"); memcpy(person.email, item->valuestring, strlen(item->valuestring)); item = cJSON_GetObjectItem(object, "age"); person.age = (int)item->valueint; item = cJSON_GetObjectItem(object, "height"); person.height = (float)item->valuedouble;
5、最后别忘了释放内存。
cJSON_Delete(root);
四、常见问题FAQs
Q1: cJSON如何解析嵌套的JSON对象?
A1: cJSON通过递归的方式解析嵌套的JSON对象,可以使用cJSON_GetObjectItem()
函数逐层获取嵌套对象的键值对。
cJSON* parent = cJSON_GetObjectItem(root, "parentKey"); cJSON* child = cJSON_GetObjectItem(parent, "childKey");
Q2: cJSON如何处理数组类型的数据?
A2: cJSON通过链表的方式来处理数组类型的数据,可以使用cJSON_GetArrayItem()
函数来获取数组中的元素。
cJSON* array = cJSON_GetObjectItem(root, "arrayKey"); cJSON* element = cJSON_GetArrayItem(array, 0); // 获取数组的第一个元素
Q3: cJSON如何释放已分配的内存?
A3: cJSON提供了cJSON_Delete()
函数来释放已分配的内存,在解析完成后,应调用该函数来避免内存泄漏。
cJSON_Delete(root); // 释放根对象及其所有子对象
以上就是关于“cjson解析json”的问题,朋友们可以点击主页了解更多内容,希望可以够帮助大家!
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1493070.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复