cJSON使⽤详细教程⼀个轻量级C语⾔JSON解析器
1. JSON与cJSON
JSON —— 轻量级的数据格式
全称 JavaScript Object Notation,即 JS对象简谱,是⼀种轻量级的数据格式。
它采⽤完全独⽴于编程语⾔的⽂本格式来存储和表⽰数据,语法简洁、层次结构清晰,易于⼈阅读和编写,同时也易于机器解析和⽣成,有效的提升了⽹络传输效率。
JSON语法规则
基于jsp的简易聊天室设计JSON对象是⼀个⽆序的"名称/值"键值对的集合:
以"{“开始,以”}"结束,允许嵌套使⽤;
python请求并解析json数据每个名称和值成对出现,名称和值之间使⽤":"分隔;
键值对之间⽤","分隔
在这些字符前后允许存在⽆意义的空⽩符;
对于键值,可以有如下值:
⼀个新的json对象
数组:使⽤"[“和”]"表⽰
数字:直接表⽰,可以是整数,也可以是浮点数
字符串:使⽤引号"表⽰
字⾯值:false、null、true中的⼀个(必须是⼩写)
⽰例如下:
{
"name":"mculover666",
"age":22,
"weight":55.5
"address":
{
"country":"China",
"zip-code":111111
},
"skill":["c","Java","Python"],
"student":false
}
cJSON
cJSON是⼀个使⽤C语⾔编写的JSON数据解析器,具有超轻便,可移植,单⽂件的特点,使⽤MIT开源协议。
cJSON项⽬托管在Github上,仓库地址如下:
使⽤Git命令将其拉取到本地:
git clone github/DaveGamble/cJSON.git
从Github拉取cJSON源码后,⽂件⾮常多,但是其中cJSON的源码⽂件只有两个:
cJSON.h
cJSON.c
使⽤的时候,只需要将这两个⽂件复制到⼯程⽬录,然后包含头⽂件cJSON.h即可,如下:
#include"cJSON.h"
2. cJSON数据结构和设计思想
cJSON的设计思想从其数据结构上就能反映出来。
cJSON使⽤cJSON结构体来表⽰⼀个JSON数据,定义在cJSON.h中,源码如下:
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
什么叫反码/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String  and type == cJSON_Raw */
char*valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char*string;
} cJSON;
cJSON的设计很巧妙。
比ubuntu好用的系统
⾸先,它不是将⼀整段JSON数据抽象出来,⽽是将其中的⼀条JSON数据抽象出来,也就是⼀个键值对,⽤上⾯的结构体 strcut cJSON 来表⽰,其中⽤来存放值的成员列表如下:
String:⽤于表⽰该键值对的名称;
type:⽤于表⽰该键值对中值的类型;
valuestring:如果键值类型(type)是字符串,则将该指针指向键值;
valueint:如果键值类型(type)是整数,则将该指针指向键值;
valuedouble:如果键值类型(type)是浮点数,则将该指针指向键值;
python爬虫新手入门教程其次,⼀段完整的JSON数据中由很多键值对组成,并且涉及到键值对的查、删除、添加,所以使⽤链表来存储整段JSON数据,如上⾯的代码所⽰:
next指针:指向下⼀个键值对
prev指针指向上⼀个键值对
最后,因为JSON数据⽀持嵌套,所以⼀个键值对的值会是⼀个新的JSON数据对象(⼀条新的链表),也有可能是⼀个数组,⽅便起见,在cJSON中,数组也表⽰为⼀个数组对象,⽤链表存储,所以:
在键值对结构体中,当该键值对的值是⼀个嵌套的JSON数据或者⼀个数组时,由child指针指向该条新链表。
3. JSON数据封装
封装⽅法
封装JSON数据的过程,其实就是创建链表和向链表中添加节点的过程。
⾸先来讲述⼀下链表中的⼀些术语:
头指针:指向链表头结点的指针;
头结点:不存放有效数据,⽅便链表操作;
⾸节点:第⼀个存放有效数据的节点;
尾节点:最后⼀个存放有效数据的节点;
明⽩了这⼏个概念之后,我们开始讲述创建⼀段完整的JSON数据,即如何创建⼀条完整的链表。
① 创建头指针:
cJSON* cjson_test =NULL;
② 创建头结点,并将头指针指向头结点:
cjson_test =cJSON_CreateObject();
③ 尽情的向链表中添加节点:
cJSON_AddNullToObject(cJSON * const object, const char * const name);
cJSON_AddTrueToObject(cJSON * const object, const char * const name);
cJSON_AddFalseToObject(cJSON * const object, const char * const name);
cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
cJSON_AddObjectToObject(cJSON * const object, const char * const name);
cJSON_AddArrayToObject(cJSON * const object, const char * const name);
输出JSON数据
上⾯讲述,⼀段完整的JSON数据就是⼀条长长的链表,那么,如何打印出这段JSON数据呢?cJSON提供了⼀个API,可以将整条链表中存放的JSON信息输出到⼀个字符串中:
(char*)cJSON_Print(const cJSON *item);
使⽤的时候,只需要接收该函数返回的指针地址即可。
封装数据和打印数据⽰例
单纯的讲述⽅法还不够,下⾯⽤⼀个例⼦来说明,封装出开头给出的那段JSON数据:
#include<stdio.h>
#include"cJSON.h"
int main(void)
{
cJSON* cjson_test =NULL;
cJSON* cjson_address =NULL;
cJSON* cjson_skill =NULL;
char* str =NULL;
/* 创建⼀个JSON数据对象(链表头结点) */
cjson_test =cJSON_CreateObject();
/* 添加⼀条字符串类型的JSON数据(添加⼀个链表节点) */
cJSON_AddStringToObject(cjson_test,"name","mculover666");
/* 添加⼀条整数类型的JSON数据(添加⼀个链表节点) */
cJSON_AddNumberToObject(cjson_test,"age",22);
/* 添加⼀条浮点类型的JSON数据(添加⼀个链表节点) */
cJSON_AddNumberToObject(cjson_test,"weight",55.5);
/
* 添加⼀个嵌套的JSON数据(添加⼀个链表节点) */
cjson_address =cJSON_CreateObject();
cJSON_AddStringToObject(cjson_address,"country","China"); cJSON_AddNumberToObject(cjson_address,"zip-code",111111); cJSON_AddItemToObject(cjson_test,"address", cjson_address);easyui datagrid 合计
/* 添加⼀个数组类型的JSON数据(添加⼀个链表节点) */
cjson_skill =cJSON_CreateArray();
cJSON_AddItemToArray(cjson_skill,cJSON_CreateString("C")); cJSON_AddItemToArray(cjson_skill,cJSON_CreateString("Java")); cJSON_AddItemToArray(cjson_skill,cJSON_CreateString("Python")); cJSON_AddItemToObject(cjson_test,"skill", cjson_skill);
/* 添加⼀个值为 False 的布尔类型的JSON数据(添加⼀个链表节点) */ cJSON_AddFalseToObject(cjson_test,"student");
/* 打印JSON对象(整条链表)的所有数据 */
str =cJSON_Print(cjson_test);
printf("%s\n", str);
return0;
}
编译运⾏:
gcc cJSON.c example1.c -
实验结果如图:
该JSON数据链表的关系如图:
4. cJSON数据解析
解析⽅法
解析JSON数据的过程,其实就是剥离⼀个⼀个链表节点(键值对)的过程。
解析⽅法如下:
① 创建链表头指针:
cJSON* cjson_test =NULL;
② 解析整段JSON数据,并将链表头结点地址返回,赋值给头指针:
解析整段数据使⽤的API只有⼀个:
(cJSON *)cJSON_Parse(const char*value);
③ 根据键值对的名称从链表中取出对应的值,返回该键值对(链表节点)的地址(cJSON *)cJSON_GetObjectItem(const cJSON *const object,const char*const string);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。