cJSON库的解析与使用
- 1、JSON格式简介
- 1.1、cjson数据结构形式
- 1.2、cjson语法规则
- 1.3、cjson的数据类型
- 2、cJSON核心结构体
- 3、封装JSON格式
- 3.1、创建一个对象,并向这个对象里添加字符串和整型键值:
- 3.2、创建一个数组,并向数组添加一个字符串和一个数字
- 3.3、 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字
- 4、解析json得到数据
- 4.1、解析流程
- 4.2、解析没有父节点的
- 4.3、解析object
- 4.4、解析数组
- 4.5、解析数组中带对象
1、JSON格式简介
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。(来自“开源中国”资料)。
cJSON从名字可知,整个项目都是以极标准的C来写的,意思说,可以跨各种平台使用了。 cJSON 是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。
cJSON是一个仅有一个.h文件,一个.c文件组成的JSON解析器,它是由纯C(ANSI C89)实现的,跨平台性较好。使用的时候,自己创建好一个main.c文件后,将头文件include进去。
#include "cJSON.h"
如果是在linux的主机上上,请使用以下命令进行编译(链接libm库):
gcc *.c cJSON.c -lm
1.1、cjson数据结构形式
(1)、对象(object):一个对象以 { 开始,并以 } 结束。一个对象包含一系列非排序的名称/值对,每个名称/值对之间使用”,”分隔。
(2)、名称/值(collection):名称和值之间使用”:”隔开。一个名称是一个字符串;一个值 (value)可以是双引号括起来的字符串(string)、数值(number)、true、false、null、对象(object)或者数组(array)。这些结构可以嵌套。
1.2、cjson语法规则
(1)、数据在键值对中;
(2)、数据由逗号分隔;
(3)、花括号保存对象;
(4)、方括号保存数组。
1.3、cjson的数据类型
/* 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
这里的类型就是cJSON核心结构体中的type的类型
2、cJSON核心结构体
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;
结构体参数说明:
参数 | 描述 |
struct cJSON *next,*prev | 遍历数组或对象链的前向或后向链表指针 |
struct cJSON *child | 数组或对象的孩子节点 |
int type | key的类型 |
char *valuestring | 字符串值 |
int valueint | 整数值 |
double valuedouble | 浮点数值 |
char *string | key的名字 |
说明:
1、cJSON是使用链表来存储数据的,其访问方式很像一颗树。每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层。只有节点是对象或数组时才可以有孩子节点。
2、type是键(key)的类型,一共有7种取值,分别是:False,Ture,NULL,Number,String,Array,Object。
若是Number类型,则valueint或valuedouble中存储着值。若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值。
若是String类型的,则valuestring中存储着值,可以访问valuestring得到值。
3、string中存放的是这个节点的名字,可理解为key的名称。
3、封装JSON格式
一般流程:创建一个对象或数组,在向数组中添加你想要的值
3.1、创建一个对象,并向这个对象里添加字符串和整型键值:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
int main(int argc,char ** argv)
{
cJSON * usr;
cJSON *arry;
usr=cJSON_CreateObject(); //创建根数据对象
cJSON_AddStringToObject(usr,"name","fengxin"); //加入键值,加字符串
cJSON_AddStringToObject(usr,"passwd","123");
cJSON_AddNumberToObject(usr,"num",1); //加整数
char *out = cJSON_Print(usr); //将json形式打印成正常字符串形式
printf("%s\n",out);
// 释放内存
cJSON_Delete(usr);
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
运行结果:
3.2、创建一个数组,并向数组添加一个字符串和一个数字
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
void create_js(void)
{
cJSON *root, *js_body;
root = cJSON_CreateArray(); //创建跟数组对象 "["开头 "]"结尾
cJSON_AddItemToArray(root, cJSON_CreateString("Hello world")); //加字符串
cJSON_AddItemToArray(root, cJSON_CreateNumber(10)); //加整数
char *s = cJSON_PrintUnformatted(root); //将json形式打印成正常字符串形式
if(s)
{
printf(" %s \n",s); //打印输出
free(s);
}
if(root) cJSON_Delete(root);//释放内存
}
int main(int argc,char ** argv)
{
create_js();
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
运行效果:
3.3、 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
int create_js(void)
{
cJSON *root, *js_body, *js_list;
root = cJSON_CreateObject(); //创建一个object "{"开头 "}"结尾
cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray()); //向object中加入body和一个数组"["开头 "]"结尾
cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject()); //在数组中加入一个object "{"开头 "}"结尾
cJSON_AddStringToObject(js_list,"name","fengxin"); //向数组中的object中加入字符串
cJSON_AddNumberToObject(js_list,"status",100); //向数组中的object中加入整数
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
if(root)
cJSON_Delete(root);
return 0;
}
int main(int argc,char ** argv)
{
create_js();
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
运行效果:
由浅入深,向这些简单的嵌套回了,更复杂的也很简单,只不过多费点力。
4、解析json得到数据
4.1、解析流程
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);
4.2、解析没有父节点的
{
name:fengxin,
passwd:123,num:1
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
int main(int argc,char ** argv)
{
cJSON *json,*json_name,*json_passwd,*json_num;
char* out="{\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}";
json = cJSON_Parse(out); //解析成json形式
json_name = cJSON_GetObjectItem( json , "name" ); //获取键值内容
json_passwd = cJSON_GetObjectItem( json , "passwd" );
json_num = cJSON_GetObjectItem( json , "num" );
printf("name:%s,passwd:%s,num:%d\n",json_name->valuestring,json_passwd->valuestring,json_num->valueint);
cJSON_Delete(json); //释放内存
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
运行效果:
4.3、解析object
创建JSON字符串文本文档1.txt:
{
"list":
{
"name":"xiao hong",
"age":10
},
"other":
{
"name":"hua hua"
}
}
解析:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "cJSON.h"
int cJSON_to_str(char *s);
/*获取1.txt中JSON字符串*/
void dofile(char *filename)
{
FILE *f;
int len;
char *data;
f=fopen(filename,"rb");
fseek(f,0,SEEK_END);
len=ftell(f);
fseek(f,0,SEEK_SET);
data=(char*)malloc(len+1);
fread(data,1,len,f);
fclose(f);
printf("read file %s complete, len=%d.\n",filename,len);
printf("data is %s\n",data);
cJSON_to_str(data); /*调用JSON解析*/
free(data);
}
int cJSON_to_str(char *s)
{
printf("%s\n",s);
cJSON *root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}
/*获取list节点类型*/
cJSON *js_list = cJSON_GetObjectItem(root, "list");
if(!js_list) {
printf("no list!\n");
return -1;
}
printf("list type is %d\n",js_list->type);
/*获取name类型及其字符串的值*/
cJSON *name = cJSON_GetObjectItem(js_list, "name");
if(!name) {
printf("No name !\n");
return -1;
}
printf("name type is %d\n",name->type);
printf("name is %s\n",name->valuestring);
/*获取age的类型及其值*/
cJSON *age = cJSON_GetObjectItem(js_list, "age");
if(!age) {
printf("no age!\n");
return -1;
}
printf("age type is %d\n", age->type);
printf("age is %d\n",age->valueint);
/*获取other类型*/
cJSON *js_other = cJSON_GetObjectItem(root, "other");
if(!js_other) {
printf("no list!\n");
return -1;
}
printf("list type is %d\n",js_other->type);
/*获取name的类型及其值*/
cJSON *js_name = cJSON_GetObjectItem(js_other, "name");
if(!js_name) {
printf("No name !\n");
return -1;
}
printf("name type is %d\n",js_name->type);
printf("name is %s\n",js_name->valuestring);
if(root)
cJSON_Delete(root); /*释放root*/
return 0;
}
int main(int argc, char **argv)
{
dofile(argv[1]);
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
运行效果:
./aaa 1.txt
4.4、解析数组
创建JSON字符串文本文档1.txt:
{
"list":
[
"name1",
"name2"
]
}
解析:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "cJSON.h"
int cJSON_to_str(char *s);
void dofile(char *filename)
{
FILE *f;
int len;
char *data;
f=fopen(filename,"rb");
fseek(f,0,SEEK_END);
len=ftell(f);
fseek(f,0,SEEK_SET);
data=(char*)malloc(len+1);
fread(data,1,len,f);
fclose(f);
printf("read file %s complete, len=%d.\n",filename,len);
printf("data is %s\n",data);
cJSON_to_str(data);
free(data);
}
int cJSON_to_str(char *s)
{
printf("%s\n",s);
cJSON *root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}
cJSON *js_list = cJSON_GetObjectItem(root, "list");
if(!js_list){
printf("no list!\n");
return -1;
}
int array_size = cJSON_GetArraySize(js_list);
printf("array size is %d\n",array_size);
int i = 0;
cJSON *item;
for(i=0; i< array_size; i++) {
item = cJSON_GetArrayItem(js_list, i);
printf("item type is %d\n",item->type);
printf("%s\n",item->valuestring);
}
if(root)
cJSON_Delete(root);
return 0;
}
int main(int argc, char **argv)
{
dofile(argv[1]);
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
./aaa 1.txt
运行效果:
4.5、解析数组中带对象
创建JSON字符串文本文档1.txt:
{
"list": [
{
"name": "xiao hong",
"age": 10
},
{
"name": "hua hua",
"age": 11
}
]
}
解析:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "cJSON.h"
int cJSON_to_str(char *s);
void dofile(char *filename)
{
FILE *f;
int len;
char *data;
f=fopen(filename,"rb");
fseek(f,0,SEEK_END);
len=ftell(f);
fseek(f,0,SEEK_SET);
data=(char*)malloc(len+1);
fread(data,1,len,f);
fclose(f);
printf("read file %s complete, len=%d.\n",filename,len);
printf("data is %s\n",data);
cJSON_to_str(data);
free(data);
}
int cJSON_to_str(char *s)
{
cJSON* root = cJSON_Parse(s);
if(!root) {
printf("get root faild !\n");
return -1;
}
cJSON* list = cJSON_GetObjectItem(root, "list");
if(!list){
printf("no list!\n");
return -1;
}
printf("list type is %d\n", list->type);
int array_size = cJSON_GetArraySize(list);
printf("array size is :%d\n", array_size);
for(int i = 0 ; i < array_size ; i++){
cJSON *item = cJSON_GetArrayItem(list, i);
//char *str = cJSON_PrintUnformatted(item);
cJSON* name = cJSON_GetObjectItem(item, "name");
printf("name type is %d\n", name->type);
printf("name:%s\n", name->valuestring);
cJSON* age = cJSON_GetObjectItem(item, "age");
printf("age type is %d\n", age->type);
printf("age:%d\n", age->valueint);
}
if(root)
cJSON_Delete(root);
}
int main(int argc, char **argv)
{
dofile(argv[1]);
return 0;
}
编译:
gcc cJSON.c main.c -o aaa -lm
运行效果:
./aaa 1.txt
好了,到这里大部分都差不多了,更多的嵌套也都大同小异。。